这是一份关于开发和部署 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.