我想从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
...
答案 0 :(得分:4)
我担心你在这里尝试做的事情本质上是脆弱的,只能通过以前版本的Django上的幸运事故来工作,并且不适用于Django 1.7或任何未来版本的Django。 (更新:它也会让你容易受到“shellshock”bash bug的攻击,而WSGI通常不会。)
基本问题是WSGI环境仅在每个请求的基础上可用,但您正在尝试基于它为Django进程设置全局配置。这是低效的并且在概念上被破坏了(为什么每次请求进入时都会一次又一次地重新设置OS环境变量?如果不同的请求具有不同的WSGI环境会怎么样?)并且它只能在Django等待的时候才能工作配置自己,直到第一个请求到达。
但Django在以前版本中的启动顺序的不可预测的时间和顺序引起了问题。例如,当在本地开发中使用runserver时,由于验证检查,Django会急切地自行配置,但在生产环境下,它只能懒惰地配置它(你依赖它),这意味着有时候导入会以不同的顺序发生,生产中的循环进口将在runserver下无法重现。
Django 1.7包含一个改进的启动序列,以解决这些问题,使启动序列在开发和生产之间可预测和一致,并允许用户显式注册代码以在启动时运行(通过AppConfig.ready()
)。这样做的副作用是在您的流程启动时配置设置(特别是在django.setup()
中调用get_wsgi_application()
),而不是等到第一个请求进入。
如果您只在此服务器上运行一个Django站点,我只需将您的配置移动到普通环境变量而不是Apache配置中的SetEnv
,并避免整个问题。
如果您正在运行多个Django站点,这些站点需要通过单个Apache服务器进行不同的配置,那么这将无效。在这种情况下,也许更熟悉Apache和mod_wsgi
的人可以为您提供有关如何以可靠的方式将环境变量从Apache配置传递到Django进程的建议;在尝试通过一台服务器运行多个独立配置的站点时,我个人发现了mod_wsgi
混淆且容易出错的流程模型(实际上是流程模型,因为根据配置方式不止一个)。我发现使用像gunicorn或uwsgi这样的专用WSGI服务器并使用Apache(或nginx)代理更简单。然后,使用单独的操作系统环境运行多个gunicorn / uwsgi进程非常简单。