通过 mod_wsgi 从 apache 传递环境变量以在 django 1.11 设置中使用

Passing environment variables from apache via mod_wsgi to use in django 1.11 settings

找到了这个问题的几个版本,例如 Django get environment variables from apache,但是到目前为止我发现的建议似乎不适用于最新的 LTS django (1.11)。

我有一个 apache 配置,其中包含许多环境变量,不限于数据库的连接凭据。我使用它使我的代码在 dev/prod 等

之间可移植

我的 apache conf 只是使用 SetEnv 来传递一些变量。

我尝试了两种不同风格的方法来使用这些变量,两者似乎都遇到了同样的问题;在我们写入环境之前它需要读取设置文件,而设置文件需要来自环境的值。

我的两个变体是;

import os
import django
from django.core.handlers.wsgi import WSGIHandler

from django.core.wsgi import get_wsgi_application

_application = get_wsgi_application()

def application(environ, start_response):
  for key in [keys...]:
    if environ.get(key):
        os.environ[key] = environ.get(key)
  return _application(environ, start_response)

import os
import django
from django.core.handlers.wsgi import WSGIHandler

class WSGIEnvironment(WSGIHandler):
    def __call__(self, environ, start_response):
        for key in [keys...]:
            if environ.has_key(key):
                print "Key: %s = %s" % (key,environ[key])
                os.environ[key] = environ[key]
        return super(WSGIEnvironment, self).__call__(environ, start_response)

os.environ.setdefault("DJANGO_SETTINGS_MODULE", 'apiClient.settings')
django.setup(set_prefix=False)
application = WSGIEnvironment()

无论哪种方式,我都试图将设置中的值用作;

KEY = "thing"

if os.environ.has_key("KEY"):
    KEY = os.environ["KEY"]

您不能使用 SetEnv,因为在处理第一个请求之前会评估设置文件。根据每个请求设置环境变量 WSGI 环境值总是一个坏主意,并且会导致问题,所以无论如何你都不应该这样做。

结果是您无法从 Apache 配置文件设置环境变量。从 WSGI 脚本文件中设置它们。如果它们是不应该添加到 Git 存储库的东西,请在特定主机上使用某种格式的值创建一个文件,并让 WSGI 脚本文件从本地主机读取该文件以在第一次设置它们时加载并在执行任何 Django 代码之前。

您必须将 Django 应用程序的初始化推迟到第一个请求。在您的 wsgi.py:

中有这样的内容
from django.core.wsgi import get_wsgi_application
_application = None
def application(environ, start_response):
    global _application
    if _application == None:
        for key in environ:
            if key.startswith('ENV_'):
                os.environ[key[4:]] = environ[key]
        _application = get_wsgi_application()
    return _application(environ, start_response)

遗憾的是mod_wsgi中似乎没有设置启动守护进程时的初始环境的选项,就像mod_fastcgi。

对于 Django > 1.7 get_wsgi_application 调用 django.setup() 来初始化设置。因此,如果此时您的环境变量未设置,您将不会在设置中看到它们。

要绕过它,请在准备好之前不要真正调用 get_wsgi_application。这对我有用 wsgi.py:

def application(environ, start_response):
    os.environ['APPLICATION_ENV'] = environ.get('APPLICATION_ENV', None)
    return get_wsgi_application()(environ, start_response)