从Apache通过mod_wsgi传递环境变量至Django 1.11配置
Fixing Apache SetEnv Environment Variables in Django 1.11
I've run into this exact issue with Django 1.11 before—your existing solutions aren't working because Django loads your settings module before your WSGI callback has a chance to set the environment variables. Let's break down why your current code fails, then fix it properly.
Why Your Current Solutions Aren't Working
Both of your approaches set os.environ variables after Django has already initialized:
- 方案一: You call
get_wsgi_application()first, which immediately loads yoursettings.pyand runs all its top-level code. By the time you setos.environin theapplicationfunction, your settings have already been evaluated with the old (missing) environment values. - 方案二:
django.setup()triggers the same settings load before your customWSGIEnvironmentclass gets to process the request. The environment variables are set too late.
The Correct Django 1.11-Compatible Solution
We need to sync Apache's environ variables to os.environ BEFORE Django loads your settings. Here's how to modify your wsgi.py:
import os from django.core.wsgi import get_wsgi_application # List all environment variables you need from Apache SetEnv REQUIRED_ENV_VARS = ["KEY", "DB_HOST", "DB_NAME", "DB_USER", "DB_PASSWORD"] # Initialize the Django application only once _application = None def application(environ, start_response): global _application # Sync Apache's environment variables to os.environ FIRST for var_name in REQUIRED_ENV_VARS: if var_name in environ: os.environ[var_name] = environ[var_name] # Initialize Django only on the first request if _application is None: os.environ.setdefault("DJANGO_SETTINGS_MODULE", "apiClient.settings") _application = get_wsgi_application() return _application(environ, start_response)
How This Works:
- First Request: When the first request hits your server, we first copy all required variables from Apache's
environintoos.environ. Then we initialize Django's WSGI application, which loads yoursettings.py—now the settings can read the newly set environment variables. - Subsequent Requests: The
_applicationvariable is already initialized, so we skip the setup step and just pass the request through. Sinceos.environis process-wide, the variables stay set for all future requests.
Update Your Settings.py
Modify your settings to safely read the environment variables (use get() to handle cases where a variable might be missing):
import os # Your example KEY variable with a default KEY = os.environ.get("KEY", "thing") # Database configuration using environment variables DATABASES = { "default": { "ENGINE": "django.db.backends.mysql", # or your DB engine "NAME": os.environ.get("DB_NAME"), "USER": os.environ.get("DB_USER"), "PASSWORD": os.environ.get("DB_PASSWORD"), "HOST": os.environ.get("DB_HOST"), } }
Pro Tips:
- Avoid
has_key(): This method is deprecated in Python 3. Usevar in os.environoros.environ.get()instead (Django 1.11 supports both Python 2.7 and 3.5+). - Logging: Add logging to verify variables are being set correctly (helpful for debugging):
import logging logger = logging.getLogger(__name__) # Inside the application function, after setting os.environ: logger.debug(f"Synced environment variables: {[var for var in REQUIRED_ENV_VARS if var in os.environ]}") - Mod_wsgi Daemon Mode: If you're using mod_wsgi in daemon mode, ensure your
SetEnvdirectives are in the correctVirtualHostorLocationblock so the daemon process inherits them.
内容的提问来源于stack exchange,提问作者Steven Franklin
相关产品推荐
相关产品推荐

