用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的相关知识,可以找到相当多的绝佳资源。 我们喜欢去的几个地方:

基本配置

为了配置基于 mod_python 的 Django,首先要安装有可用的 mod_python 模块的 Apache。 这通常意味着应该有一个 LoadModule 指令在 Apache 配置文件中。 它看起来就像是这样:

  1. 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. 例如:

  1. <Location "/">
  2. SetHandler python-program
  3. PythonHandler django.core.handlers.modpython
  4. SetEnv DJANGO_SETTINGS_MODULE mysite.settings
  5. PythonDebug Off
  6. </Location>

要确保把 DJANGO_SETTINGS_MODULE 中的 mysite.settings 项目换成与你的站点相应的内容。

它告诉 Apache,任何在 / 这个路径之后的 URL 都使用 Django 的 mod_python 来处理。 它 将 DJANGO_SETTINGS_MODULE 的值传递过去,使得 mod_python 知道这时应该使用哪个配置。

注意这里使用 ``指令而不是 。 后者用于指向你的文件系统中的一个位置,然而 ``

System Message: WARNING/2 (&lt;string&gt;, line 403); backlink

Inline literal start-string without end-string.

System Message: WARNING/2 (&lt;string&gt;, line 403); backlink

Inline literal start-string without end-string.

System Message: WARNING/2 (&lt;string&gt;, line 403); backlink

Inline literal start-string without end-string.

System Message: WARNING/2 (&lt;string&gt;, line 403); backlink

Inline literal start-string without end-string.

System Message: ERROR/3 (&lt;string&gt;, line 405)

Unexpected indentation.

指向一个 Web 站点的 URL 位置。 ````System Message: WARNING/2 (&lt;string&gt;, line 405); _backlink_Inline literal start-string without end-string.System Message: WARNING/2 (&lt;string&gt;, line 405); _backlink_Inline literal start-string without end-string.

Apache 可能不但会运行在你正常登录的环境中,也会运行在其它不同的用户环境中;也可能会有不同的文件路径或 sys.path。 你需要告诉 mod_python 如何去寻找你的项目及 Django 的位置。

  1. PythonPath "['/path/to/project', '/path/to/django'] + sys.path"

你也可以加入一些其它指令,比如 PythonAutoReload Off 以提升性能。 查看 mod_python 文档获得详细的指令列表。

注意,你应该在成品服务器上设置 PythonDebug Off 。如果你使用 PythonDebug On 的话,在程序产生错误时,你的用户会看到难看的(并且是暴露的) Python 回溯信息。 如果你把 PythonDebug 置 On,当mod_python出现某些错误,你的用户会看到丑陋的(也会暴露某些信息)Python的对错误的追踪的信息。

重启 Apache 之后所有对你的站点的请求(或者是当你用了 &lt;VirtualHost&gt; 指令后则是虚拟主机)都会由 Djanog 来处理。

在同一个 Apache 的实例中运行多个 Django 程序

在同一个 Apache 实例中运行多个 Django 程序是完全可能的。 当你是一个独立的 Web 开发人员并有多个不同的客户时,你可能会想这么做。

只要像下面这样使用 VirtualHost 你可以实现:

  1. NameVirtualHost *
  2. <VirtualHost *>
  3. ServerName www.example.com
  4. # ...
  5. SetEnv DJANGO_SETTINGS_MODULE mysite.settings
  6. </VirtualHost>
  7. <VirtualHost *>
  8. ServerName www2.example.com
  9. # ...
  10. SetEnv DJANGO_SETTINGS_MODULE mysite.other_settings
  11. </VirtualHost>

如果你需要在同一个 VirtualHost 中运行两个 Django 程序,你需要特别留意一下以 确保 mod_python 的代码缓存不被弄得乱七八糟。 使用 PythonInterpreter 指令来将不 同的 &lt;Location&gt; 指令分别解释:

  1. <VirtualHost *>
  2. ServerName www.example.com
  3. # ...
  4. <Location "/something">
  5. SetEnv DJANGO_SETTINGS_MODULE mysite.settings
  6. PythonInterpreter mysite
  7. </Location>
  8. <Location "/otherthing">
  9. SetEnv DJANGO_SETTINGS_MODULE mysite.other_settings
  10. PythonInterpreter mysite_other
  11. </Location>
  12. </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:

  1. <Location "/media/">
  2. SetHandler None
  3. </Location>

Location 改成你的media文件所处的根目录。

你也可以使用 &lt;LocationMatch&gt; 来匹配正则表达式。 比如,下面的写法将Django定义到网站的根目录,并且显式地将 media 子目录以及任何以 .jpg.gif , 或者 .png 结尾的URL屏蔽掉:

  1. <Location "/">
  2. SetHandler python-program
  3. PythonHandler django.core.handlers.modpython
  4. SetEnv DJANGO_SETTINGS_MODULE mysite.settings
  5. </Location>
  6. <Location "/media/">
  7. SetHandler None
  8. </Location>
  9. <LocationMatch "\.(jpg|gif|png)$">
  10. SetHandler None
  11. </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文档查看到更多的信息。