用Apache和mod_python来部署Django
目前,Apache和mod_python是在生产服务器上部署Django的最健壮搭配。
mod_python (http://www.djangoproject.com/r/mod_python/)是一个在Apache中嵌入Python的Apache插件,它在服务器启动时将Python代码加载到内存中。是一个在Apache中嵌入Python的Apache插件,它在服务器启动时将Python代码加载到内存中。) (译注:
Django 需要Apaceh 2.x 和mod_python 3.x支持。
备注
如何配置Apache超出了本书的范围,因此下面将只简单介绍必要的细节。 幸运的是,如果需要进一步学习Apache的相关知识,可以找到相当多的绝佳资源。 我们喜欢去的几个地方:
开源的Apache在线文档,位于 http://www.djangoproject.com/r/apache/docs/
Pro Apache,第三版 (Apress, 2004),作者Peter Wainwright, 位于 http://www.djangoproject.com/r/books/pro-apache/
Apache: The Definitive Guide, 第三版 (OReilly, 2002),作者Ben Laurie和Peter Laurie, 位于 http://www.djangoproject.com/r/books/apache-pra/
基本配置
为了配置基于 mod_python 的 Django,首先要安装有可用的 mod_python 模块的 Apache。 这通常意味着应该有一个 LoadModule
指令在 Apache 配置文件中。 它看起来就像是这样:
LoadModule python_module /usr/lib/apache2/modules/mod_python.so
Then, edit your Apache configuration file and add a <Location>
directive that ties a specific URL path to a specific Django installation. 例如:
<Location "/">
SetHandler python-program
PythonHandler django.core.handlers.modpython
SetEnv DJANGO_SETTINGS_MODULE mysite.settings
PythonDebug Off
</Location>
要确保把 DJANGO_SETTINGS_MODULE
中的 mysite.settings
项目换成与你的站点相应的内容。
它告诉 Apache,任何在 / 这个路径之后的 URL 都使用 Django 的 mod_python 来处理。 它 将 DJANGO_SETTINGS_MODULE
的值传递过去,使得 mod_python 知道这时应该使用哪个配置。
注意这里使用 ``指令而不是
。 后者用于指向你的文件系统中的一个位置,然而
``
System Message: WARNING/2 (<string>
, line 403); backlink
Inline literal start-string without end-string.
System Message: WARNING/2 (<string>
, line 403); backlink
Inline literal start-string without end-string.
System Message: WARNING/2 (<string>
, line 403); backlink
Inline literal start-string without end-string.
System Message: WARNING/2 (<string>
, line 403); backlink
Inline literal start-string without end-string.
System Message: ERROR/3 (<string>
, line 405)
Unexpected indentation.
指向一个 Web 站点的 URL 位置。 ````System Message: WARNING/2 (<string>
, line 405); _backlink_Inline literal start-string without end-string.System Message: WARNING/2 (<string>
, line 405); _backlink_Inline literal start-string without end-string.
Apache 可能不但会运行在你正常登录的环境中,也会运行在其它不同的用户环境中;也可能会有不同的文件路径或 sys.path。 你需要告诉 mod_python 如何去寻找你的项目及 Django 的位置。
PythonPath "['/path/to/project', '/path/to/django'] + sys.path"
你也可以加入一些其它指令,比如 PythonAutoReload Off
以提升性能。 查看 mod_python 文档获得详细的指令列表。
注意,你应该在成品服务器上设置 PythonDebug Off
。如果你使用 PythonDebug On
的话,在程序产生错误时,你的用户会看到难看的(并且是暴露的) Python 回溯信息。 如果你把 PythonDebug 置 On,当mod_python出现某些错误,你的用户会看到丑陋的(也会暴露某些信息)Python的对错误的追踪的信息。
重启 Apache 之后所有对你的站点的请求(或者是当你用了 <VirtualHost>
指令后则是虚拟主机)都会由 Djanog 来处理。
在同一个 Apache 的实例中运行多个 Django 程序
在同一个 Apache 实例中运行多个 Django 程序是完全可能的。 当你是一个独立的 Web 开发人员并有多个不同的客户时,你可能会想这么做。
只要像下面这样使用 VirtualHost
你可以实现:
NameVirtualHost *
<VirtualHost *>
ServerName www.example.com
# ...
SetEnv DJANGO_SETTINGS_MODULE mysite.settings
</VirtualHost>
<VirtualHost *>
ServerName www2.example.com
# ...
SetEnv DJANGO_SETTINGS_MODULE mysite.other_settings
</VirtualHost>
如果你需要在同一个 VirtualHost
中运行两个 Django 程序,你需要特别留意一下以 确保 mod_python 的代码缓存不被弄得乱七八糟。 使用 PythonInterpreter
指令来将不 同的 <Location>
指令分别解释:
<VirtualHost *>
ServerName www.example.com
# ...
<Location "/something">
SetEnv DJANGO_SETTINGS_MODULE mysite.settings
PythonInterpreter mysite
</Location>
<Location "/otherthing">
SetEnv DJANGO_SETTINGS_MODULE mysite.other_settings
PythonInterpreter mysite_other
</Location>
</VirtualHost>
这个 PythonInterpreter
中的值不重要,只要它们在两个 Location
块中不同。
用 mod_python 运行一个开发服务器
因为 mod_python 缓存预载入了 Python 的代码,当在 mod_python 上发布 Django 站点时,你每 改动了一次代码都要需要重启 Apache 一次。 这还真是件麻烦事,所以这有个办法来避免它: 只要 加入 MaxRequestsPerChild 1
到配置文件中强制 Apache 在每个请求时都重新载入所有的 代码。 但是不要在产品服务器上使用这个指令,这会撤销 Django 的特权。
如果你是一个用分散的 print
语句(我们就是这样)来调试的程序员,注意这 print
语 句在 mod_python 中是无效的;它不会像你希望的那样产生一个 Apache 日志。 如果你需要在 mod_python 中打印调试信息,可能需要用到 Python 标准日志包(Pythons standard logging package)。 更多的信息请参见 http://docs.python.org/lib/module-logging.html 。另一个选择是在模板页面中加入调试信息。
使用相同的Apache实例来服务Django和Media文件
Django本身不用来服务media文件;应该把这项工作留给你选择的网络服务器。 我们推荐使用一个单独的网络服务器(即没有运行Django的一个)来服务media。 想了解更多信息,看下面的章节。
不过,如果你没有其他选择,所以只能在同Django一样的Apache VirtualHost
上服务media文件,这里你可以针对这个站点的特定部分关闭mod_python:
<Location "/media/">
SetHandler None
</Location>
将 Location
改成你的media文件所处的根目录。
你也可以使用 <LocationMatch>
来匹配正则表达式。 比如,下面的写法将Django定义到网站的根目录,并且显式地将 media
子目录以及任何以 .jpg
, .gif
, 或者 .png
结尾的URL屏蔽掉:
<Location "/">
SetHandler python-program
PythonHandler django.core.handlers.modpython
SetEnv DJANGO_SETTINGS_MODULE mysite.settings
</Location>
<Location "/media/">
SetHandler None
</Location>
<LocationMatch "\.(jpg|gif|png)$">
SetHandler None
</LocationMatch>
在所有这些例子中,你必须设置 DocumentRoot
,这样apache才能知道你存放静态文件的位置。
错误处理
当你使用 Apache/mod_python 时,错误会被 Django 捕捉,它们不会传播到 Apache 那里,也不会出现在 Apache 的 错误日志
中。
除非你的 Django 设置的确出了问题。 在这种情况下,你会在浏览器上看到一个 内部服务器错误的页面,并在 Apache 的 错误日志
中看到 Python 的完整回溯信息。 错误日志
的回溯信息有多行。 当然,这些信息是难看且难以阅读的。
处理段错误
有时候,Apache会在你安装Django的时候发生段错误。 这时,基本上 总是 有以下两个与Django本身无关的原因其中之一所造成:
有可能是因为,你使用了
pyexpat
模块(进行XML解析)并且与Apache内置的版本相冲突。 详情请见 http://www.djangoproject.com/r/articles/expat-apache-crash/.也有可能是在同一个Apache进程中,同时使用了mod_python 和 mod_php,而且都使用MySQL作为数据库后端。 在有些情况下,这会造成PHP和Python的MySQL模块的版本冲突。 在mod_python的FAQ中有更详细的解释。
如果还有安装mod_python的问题,有一个好的建议,就是先只运行mod_python站点,而不使用Django框架。 这是区分mod_python特定问题的好方法。 下面的这篇文章给出了更详细的解释。 http://www.djangoproject.com/r/articles/getting-modpython-working/.
下一个步骤应该是编辑一段测试代码,把你所有django相关代码import进去,你的views,models,URLconf,RSS配置,等等。 把这些imports放进你的handler函数中,然后从浏览器进入你的URL。 如果这些导致了crash,你就可以确定是import的django代码引起了问题。 逐个去掉这些imports,直到不再冲突,这样就能找到引起问题的那个模块。 深入了解各模块,看看它们的imports。 要想获得更多帮助,像linux的ldconfig,Mac OS的otool和windows的ListDLLs(form sysInternals)都可以帮你识别共享依赖和可能的版本冲突。
一种替代方案: mod_wsgi模块
作为一个mod_python模块的替代,你可以考虑使用mod_wsgi模块(http://code.google.com/p/modwsgi/),此模块开发的时间比mod_python的开发时间离现在更近一些,在Django社区已有一些使用。,此模块开发的时间比mod_python的开发时间离现在更近一些,在Django社区已有一些使用。) 一个完整的概述超出了本书的范围,你可以从官方的Django文档查看到更多的信息。