Django 应用 (app)

如何发布我的 app ?

Django 应该使用使用标准的 Python Package Index 即 Pypi 和 Cheese Shop. 我写过一篇关于如何 轻松打包和上传 app 到 Pypi 的 教程.

如果你上传 app 到 Pypi, 建议最好在你的项目名前加上 "django-" 前缀.

(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 应该有上级目录的吧?)
  • 可以包含模板, 供使用者参考

什么是可复用 app?

一个 Django app, 一个能够轻松嵌入到 project 的 app, 提供一个非常明确的功能. 它们应该专注并遵循 Unix 哲学 -- "做一件事并把它做好". 更多相关信息请参考 James Bennett 的 Djangocon talk.

Application 模块

(yospaly: 以下所有大写单词, 如: APP, MODEL 等, 替换成你项目中真实的 app 名或 model 名.)

Admin
  • 非必须
  • 放在 APP/admin.py 文件中
  • Admin 的 MODEL 类命名为 MODELAdmin

上下文处理器
  • 放在 APP/context_processors.py 文件中

内容源
  • 放在 APP/feeds.py 文件中

表单
  • 放在 APP/forms.py 文件中

Managers
  • 放在 APP/managers.py 文件中

中间件
  • 放在 APP/middleware.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

URLs
  • 放在 APP/urls (.py 文件或目录) 中
  • 需要设置 name 属性以便能够被反查; name 属性设置成 APP_MODEL_VIEW 的格式, 比如 blog_post_detail 或 blog_post_list.

视图
  • 放在 APP/views (.py 文件或目录) 中
  • 可以是任何可调用的 python 函数.
  • 视图参数应提供合理的缺省值, 并易于定制:

范例:

def register(request, success_url=None,
         form_class=RegistrationForm
         template_name='registration/registration_form.html',
         extra_context=None):

Django Projects (项目)

推荐的布局

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?

Django 中的 project 指的是一个包含设置文件, urls 链接, 以及一些 Django Apps 集合的简单结构. 这些东东可以是你自己写的, 也可以是一些包含在你的 project 内 的第三方代码.

Project 模块

设置

放在 [PROJECT]/settings.py 文件中

使用相对路径

import os
DIRNAME = os.path.dirname(__file__)

MEDIA_ROOT = os.path.join(DIRNAME, 'static')

具体环境相关的设置使用 local_settings.py 文件, 并在 settings.py 文件结尾导入它.

try:
    from local_settings import *
except ImportError:
    pass

URLs
  • 放在 PROJECT/urls.py 文件中
  • 应包含最少的逻辑代码, 多数情况下只作为一个指针, 指向你 apps 各自的 URL 配置.

部署

Project 的环境初始化

.. index:: virtualenv, pip

文件系统布局

Note

本文档严重偏向 Unix 风格的文件系统, 要在其它操作系统上使用需要做些额外的修改.

Virtualenv 对于 Python 项目来说是必须的. 它提供一个隔离不同 Python 运行环境的方法. 典型的, 我们在 /opt/webapps/<site_name> 部署生产环境站点, 在 ~/webapps/<site_name> 目录部署我们的开发环境站点. 每个 project 有它自己的 virtualenv, virtualenv 还充当 project 所有相关代码的根目录. 我们使用 pipvirtualenv 添加必要的包.

引导过程看上去是这样的:

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 函数以节省时间.

.. index:: pip, requirements.txt


打包

成功部署的关键之一是, 保证你开发环境下的软件尽可能接近部署环境下的软件. Pip 提供了一个简单的重现方法, 让你在任何系统上都能非常一致的部署 Python 项目. 任何需要第三方库的 app 都应该包含一个名为 requirements.txtpip 规格文件. Projects 应到负责汇集所有 app 的规格文件, 并在根据需要添加其它规格.

你的规格文件中要包含些什么

我们的经验是, 任何应用程序, 只要你的操作系统默认没附带. 唯一需要从我们的规格文件中剔除的几个包是 PIL, 数据库驱动和其它 pip 不能安装的包. 这些被剔除的规格放在 :ref:`project's README <projects-layout>` 文件中加以说明.

服务器

Note

部署架构很大程度上取决于站点的流量. 下面描述的设置对我们来说, 在大多数情况下工作的最好.

我们基于 Linux 和 PostgreSQL 后端数据库部署 Django, Nginx 进程作为前端代理, 处在其后的是 Apache 和 mod_wsgi.

.. index:: Nginx

Nginx

Nginx 是一个非常优秀的前端服务器, 速度快, 稳如磐石, 并且资源占用很少. 以下是一个典型的 Nginx 站点配置:

.. literalinclude:: /examples/nginx.conf
    :language: nginx

它都做些什么?

第一段告诉 Nginx 去哪里找托管了 Django 站点的服务器. 第二段把所有来自 www.domain.com 的请求重定向到 domain.com, 这样所有资源就都只有一个 URL 能被访问到. 最后一段承担了所有工作. 它告诉 Nginx 检查 /var/www/domain.com 中是否存在被请求的文件. 如果存在, 它返回该文件, 否则, 它将把请求转发给 Django 站点.