這是一份關於開發和部署 Django Web 框架 的動態文檔 (會隨時更新). 這些準則不該該被認爲是 絕對正確 或 惟一 使用 Django 的方法, 應該說這些最佳實踐是咱們使用框架多年來積累的經驗.css
本項目是 django-reusable-app-docs 項目 的一個分支, 這個優秀的項目是由 Brian Rosner 和Eric Holscher 創建的, 是關於如何開發和維護可複用 Django apps 方面的最佳實踐準則.html
Note前端
這份文檔的源碼放在 GitHub django-best-practices , 能夠用 Sphinx 轉換成多種文檔格式python
通常而言, 代碼應該乾淨, 簡明, 易讀. The Zen of Python (PEP 20) 是 Python 編碼實踐的權威介紹.nginx
儘量合理的遵照 Style Guide for Python Code (PEP 8).git
遵照 Django coding style.github
Django 應該使用使用標準的 Python Package Index 即 Pypi 和 Cheese Shop. 我寫過一篇關於如何 輕鬆打包和上傳 app 到 Pypi 的 教程.web
若是你上傳 app 到 Pypi, 建議最好在你的項目名前加上 "django-" 前綴.ajax
(yospaly: 如下不解其意, 望達人指點) Also note, that when below when we refer to the default place for something as a file, that also means that you can make a directory of that same name; as per normal python.數據庫
放在和 APP 目錄同級的 docs 目錄中 (你的 app 應該有上級目錄的吧?)
能夠包含模板, 供使用者參考
一個 Django app, 一個可以輕鬆嵌入到 project 的 app, 提供一個很是明確的功能. 它們應該專一併遵循 Unix 哲學 -- "作一件事並把它作好". 更多相關信息請參考 James Bennett 的Djangocon talk.
(yospaly: 如下全部大寫單詞, 如: APP, MODEL 等, 替換成你項目中真實的 app 名或 model 名.)
非必須
放在 APP/admin.py 文件中
Admin 的 MODEL 類命名爲 MODELAdmin
放在 APP/context_processors.py 文件中
放在 APP/feeds.py 文件中
放在 APP/forms.py 文件中
放在 APP/managers.py 文件中
放在 APP/middleware.py 文件中
實現儘量少的任務
放在 APP/models (.py 文件中或目錄下)
放在 APP/templates/APP/template.html 文件中
爲了儘可能標準化 Django 模板區塊 (block) 名稱, 我建議一般狀況下使用如下區塊名稱.
{% block title %}
這個區塊用來定義頁面的標題. 你的 base.html 模板極可能要在這個 tag 以外定義 站點名字 (Site's name) (即使使用了 Sites 框架), 以便可以放在全部頁面中.
{% block extra_head %}
我認爲這是個很是有用的區塊, 不少人已經以某種方式在使用了. 不少頁面常常須要在 HTML 文檔頭添加些信息, 好比 RSS 源, Javascript, CSS, 以及別的應該放在文檔頭的信息. 你能夠, 也極可能將會, 定義另外專門的區塊 (好比前面的 title 區塊) 來添加文檔頭的其它部分的信息.
{% block body %}
這個 tag 用來包含頁面的整個 body 部分. 這使得你在 app 中建立的頁面 可以替換整個頁面內容, 不只僅是正文內容. 這種作法雖不常見, 但當你須要時, 它確實是一個很是方便的 tag. 你可能還沒注意到, 我一直儘量的使 tag 名字和 HTML 標籤名稱保持一致.
{% block menu %}
你的菜單 (導航欄) 應該包含在這個區塊中. 它是針對站點級的導航, 不是 每一個頁面專屬的導航菜單.
{% block content %}
這個區塊用來放置頁面正文內容. 任何頁面正文內容均可能不同. 它不 包含任何站點導航, 信息頭, 頁腳, 或其它任何屬於 base 模板的東東.
{% block content_title %}
用來指定 content 區塊的 "title". 好比 blog 的標題. 也能夠用來 包含 content 內的導航 (譯註: 好比提綱), 或其它相似的東東. 大體都是些 頁面中並不是主要內容的東東. 我不知道這個區塊是否應該放到 content tag 內, 而且對應於前面建議的 content tag, 是否是還須要一個 main_content 區塊.
{% block header %} {% block footer %}
任何每一個頁面均可能修改的文本區域的頁面和頁腳.
{% block body_id %} {% block body_class %}
用來設置 HTML 文檔 body 標籤的 class 或 id 屬性. 在設置樣式或其它屬性時 很是有用.
{% block [section]_menu %} {% block page_menu %}
這是對應於以前建議的 menu 區塊. 用來導航一個章節或頁面.
放在 APP/templatetags/APP_tags.py 文件中
as (Context Var): This is used to set a variable in the context of the page
for (object or app.model): This is used to designate an object for an action to be taken on.
limit (num): This is used to limit a result to a certain number of results.
exclude (object or pk): The same as for, but is used to exclude things of that type.
放在 APP/tests (.py 文件或目錄) 中
Fixtures 放在 APP/fixtures/fixture.json 文件中
一般只須重寫 Django 的 testcase
放在 APP/urls (.py 文件或目錄) 中
須要設置 name 屬性以便可以被反查; name 屬性設置成 APP_MODEL_VIEW 的格式, 好比 blog_post_detail 或 blog_post_list.
放在 APP/views (.py 文件或目錄) 中
能夠是任何可調用的 python 函數.
視圖參數應提供合理的缺省值, 並易於定製:
範例:
1 2 3 4 |
def register(request, success_url=None, form_class=RegistrationForm template_name='registration/registration_form.html', extra_context=None): |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
example.com/ README settings.py urls.py docs/ This will hold the documentation for your project static/ -In production this will be the root of your MEDIA_URL css/ js/ images/ tests/ - Project level tests (Each app should also have tests) uploads/ - content imgs, etc templates/ - This area is used to override templates from your reusable apps flatpages/ comments/ example/ app1/ app2/ |
Django 中的 project 指的是一個包含設置文件, urls 連接, 以及一些 Django Apps 集合的簡單結構. 這些東東能夠是你本身寫的, 也能夠是一些包含在你的 project 內 的第三方代碼.
放在 [PROJECT]/settings.py
文件中
使用相對路徑
1 2 3 4 |
import os DIRNAME = os.path.dirname(__file__)
MEDIA_ROOT = os.path.join(DIRNAME, 'static') |
具體環境相關的設置使用 local_settings.py
文件, 並在 settings.py
文件結尾導入它.
1 2 3 4 |
try: from local_settings import * except ImportError: pass |
URLs
放在 PROJECT/urls.py 文件中
應包含最少的邏輯代碼, 多數狀況下只做爲一個指針, 指向你 apps 各自的 URL 配置.
Note
本文檔嚴重偏向 Unix 風格的文件系統, 要在其它操做系統上使用須要作些額外的修改.
Virtualenv 對於 Python 項目來講是必須的. 它提供一個隔離不一樣 Python 運行環境的方法. 典型的, 咱們在 /opt/webapps/<site_name>
部署生產環境站點, 在 ~/webapps/<site_name>
目錄部署咱們的開發環境站點. 每一個 project 有它本身的 virtualenv
, virtualenv
還充當 project 全部相關代碼的根目錄. 咱們使用 pip
爲 virtualenv
添加必要的包.
引導過程看上去是這樣的:
1 2 3 4 5 |
cd /opt/webapps virtualenv mysite.com cd mysite.com pip install -E . -r path/to/requirements.txt source bin/activate |
Tip
方便起見, 你能夠在你的 virtualenv
根目錄中建立 Django project 的符號連接. 符號連接的名字無所謂, 由於你的 project 已經在 Python 搜索路徑中. 經過給你全部的 projects 起一樣的符號連接名, 你可使用一些 方便的 bash 函數以節省時間.
成功部署的關鍵之一是, 保證你開發環境下的軟件儘量接近部署環境下的軟件. Pip 提供了一個簡單的重現方法, 讓你在任何系統上都能很是一致的部署 Python 項目. 任何須要第三方庫的 app 都應該包含一個名爲 requirements.txt
的 pip 規格文件. Projects 應到負責聚集全部 app 的規格文件, 並在根據須要添加其它規格.
你的規格文件中要包含些什麼
咱們的經驗是, 任何應用程序, 只要你的操做系統默認沒附帶. 惟一須要從咱們的規格文件中剔除的幾個包是 PIL
, 數據庫驅動和其它 pip
不能安裝的包. 這些被剔除的規格放在 :ref:project's README <projects-layout>
文件中加以說明.
Note
部署架構很大程度上取決於站點的流量. 下面描述的設置對咱們來講, 在大多數狀況下工做的最好.
咱們基於 Linux 和 PostgreSQL 後端數據庫部署 Django, Nginx 進程做爲前端代理, 處在其後的是 Apache 和 mod_wsgi.
Nginx 是一個很是優秀的前端服務器, 速度快, 穩如磐石, 而且資源佔用不多. 如下是一個典型的 Nginx 站點配置:
它都作些什麼?
第一段告訴 Nginx 去哪裏找託管了 Django 站點的服務器. 第二段把全部來自 www.domain.com
的請求重定向到 domain.com
, 這樣全部資源就都只有一個 URL 能被訪問到. 最後一段承擔了全部工做. 它告訴 Nginx 檢查 /var/www/domain.com
中是否存在被請求的文件. 若是存在, 它返回該文件, 不然, 它將把請求轉發給 Django 站點.
Warning
yospaly 注
如下涉及 Apache 的部分均未做翻譯, 咱們強烈建議使用 Nginx/Lighttpd + SCGI/FastCGI/HTTP 的方式, 儘可能不要使用繁瑣的 Apache + mod_wsgi.
Another benefit to running a frontend server is lightweight SSL proxying. Rather than having two Django instances running for SSL and non-SSL access, we can have Nginx act as the gatekeeper redirecting all requests back to a single non-SSL Apache instance listening on the localhost
. Here's what that would look like:
You can include this code at the bottom of your non-SSL configuration file.
Tip
For SSL-aware Django sites like Satchmo, you'll need to "trick" the site into thinking incoming requests are coming in via SSL, but this is simple enough to do with a small addition to the WSGI script we discuss below.
We run the Apache2 Worker MPM with mod_wsgi in daemon mode. The default settings for the MPM Worker module should be sufficient for most environments although those with a shortage of RAM may want to look into reducing the number of servers spawned. Since Nginx will be listening for HTTP(S) requests, you'll need to bind Apache to a different port. While you're at it, you can tell it to only respond to the localhost
. To do so, you'll want to edit the Listen directive
1 |
Listen 127.0.0.1:9000 |
With Apache up and running, you'll need an Apache configuration and WSGI script for each site. A typical Apache configuration for an individual site looks like this:
Tip
In a perfect world, your app would never leak memory and you can leave out the maximum-requests
directive. In our experience, setting this to a high number is nice to keep Apache's memory usage in check.
Warning
This will default to a single process with 15 threads. Django is not "officially" thread safe and some external libraries (notably a couple required for django.contrib.gis
) are known to not be thread safe. If needed the threads
and processes
arguments can be adjusted accordingly.
It links to the WSGI script within the project directory. The script is just a few lines of Python to properly setup our environment.