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

标签 django apache environment-variables django-wsgi django-1.7

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

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

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

_application = get_wsgi_application()

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

在 Django 1.7 中还有其他方法吗?

在我的/etc/apache2/sites-enabled/mysyte.conf 中我有:

<VirtualHost *:80>

    ...

    SetEnv SECRET_KEY ...
    SetEnv EMAIL_HOST ...
    SetEnv EMAIL_HOST_PASSWORD ...
    SetEnv EMAIL_HOST_USER ...
    SetEnv EMAIL_PORT 25
    ...

在我的 wsgi.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)

在我的 settings.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 或任何 future 版本的 Django 一起工作。 (更新:它还会使您可能容易受到“shellshock”bash 错误的攻​​击,而 WSGI 通常不会。)

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

但是之前版本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 进程很简单。

关于django - 如何从 Apache 读取环境变量从 Django 1.6.5 更新到 1.7,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25784462/

相关文章:

django - 缓存泡沫对象。统一码问题

Django、Twitter Streaming API(使用 Twython 或其他库)相关

mysql - 开发环境Windows/Ubuntu切换

linux - 新安装的 apache 将 html 内容作为文本提供

python - 在使用 @api_view 函数 View 时使用 drf 扩展中的 @cache_response() 装饰器

django - 如何在 django admin 中获取对象的历史记录?

php - 保留外部 URL 的查询字符串

java - 环境变量是否传递到从取消配置的 azure vm(linux) 镜像创建的新规模集实例

environment-variables - 如何将变量传递给 Bazel 目标构建?

javascript - Node.js (VS Code) 中的环境变量未定义