如何读取Apache从Django 1.6.5更新到1.7的环境变量



我想从Apache vhost-config文件中读取环境变量,并将它们存储到Django设置中。

在更新到Django 1.7之前,一切都很好,但现在坏了。

当我调用时,问题似乎出现在我的wsgi.py脚本中

_application = get_wsgi_application()

因为它在设置环境变量之前读取配置文件。

在Django 1.7中有其他方法可以做到这一点吗?

在我的/etc/apache2/站点启用/mysyte.conf中我有:

<VirtualHost *:80>
    ...
    SetEnv SECRET_KEY ...
    SetEnv EMAIL_HOST ...
    SetEnv EMAIL_HOST_PASSWORD ...
    SetEnv EMAIL_HOST_USER ...
    SetEnv EMAIL_PORT 25
    ...

在我的博客.py:

import os
from os.path import abspath, dirname
from sys import path
SITE_ROOT = dirname(dirname(abspath(__file__)))
path.append(SITE_ROOT)
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "locacle.settings.production")
_application = get_wsgi_application()
def application(environ, start_response):
    for key, value in environ.items():
        if isinstance(environ[key], str):
            os.environ[key] = environ[key]
    return _application(environ, start_response)

在我的设置中.py我有:

from os import environ
from base import *
def get_env_setting(setting):
    """ Get the environment setting or return exception """
    try:
        return environ[setting]
    except KeyError:
        error_msg = "Set the %s env variable" % setting
        raise ImproperlyConfigured(error_msg)

EMAIL_HOST = get_env_setting('EMAIL_HOST')
...

这是日志文件报告的内容:

...
mod = importlib.import_module(self.SETTINGS_MODULE)
File "/usr/lib/python2.7/importlib/__init__.py", line 37, in import_module
  __import__(name)
File "/home/www/.../settings/production.py", line 34, in <module>
  EMAIL_HOST = get_env_setting('EMAIL_HOST')
File "/home/www/...settings/production.py", line 21, in get_env_setting
  raise ImproperlyConfigured(error_msg)
ImproperlyConfigured: Set the EMAIL_HOST env variable
...

我担心你在这里尝试做的事情本质上是脆弱的,只是在Django的以前版本上偶然发生的,不会与Django 1.7或任何未来版本的Django一起工作。(更新:这也会使您可能容易受到"shellshock"bash错误的攻击,而WSGI通常不会。)

基本问题是,WSGI环境仅在每个请求的基础上可用,但您正试图基于它为Django进程设置全局配置。这是低效的,而且在概念上是错误的(为什么每次收到请求时都要一次又一次地重新设置操作系统环境变量?如果不同的请求有不同的WSGI环境怎么办?),只有当Django等待配置自己直到第一个请求到达时,它才能工作。

但是Django在以前版本中启动序列的不可预测的时间和顺序造成了问题。例如,当在本地开发中使用runserver时,由于验证检查,Django会急切地配置自己,但在生产环境下,它只会懒散地配置自己(这是你所依赖的),这意味着有时导入会以不同的顺序发生,而循环导入会在生产中突然出现,而这些导入在runserver下是不可复制的。

Django 1.7包含了一个改进的启动序列,以解决这些问题,使启动序列在开发和生产之间具有可预测性和一致性,并允许用户显式注册代码以在启动时运行(通过AppConfig.ready())。这样做的一个副作用是,设置是在进程启动时配置的(特别是在get_wsgi_application()中调用django.setup()),而不是等到第一个请求到来

如果你在这台服务器上只运行一个Django站点,我会简单地将你的配置转移到普通的环境变量中,而不是Apache配置中的SetEnv,这样就可以避免整个问题。

如果你在一个Apache服务器上运行多个Django站点,而这些站点需要不同的配置,那么这是行不通的。在这种情况下,也许更熟悉Apache和mod_wsgi的人可以为您提供如何以可靠的方式将环境变量从Apache配置传递到Django进程的建议;我个人发现,当尝试通过一台服务器运行多个独立配置的站点时,mod_wsgi的流程模型(实际上是流程模型,因为根据您的配置方式,有不止一个)令人困惑且容易出错。我发现使用像gunicorn或uwsgi这样的专用WSGI服务器并使用Apache(或nginx)代理更简单。然后,在单独的操作系统环境中运行多个gunicorn/uwsgi进程也很简单。

最新更新