#21486 closed Bug (fixed)
Backwards incompatible change in 1.6: accessing Apache mod_wsgi environment variables
Reported by: | Jon Dufresne | Owned by: | nobody |
---|---|---|---|
Component: | Core (Other) | Version: | 1.6 |
Severity: | Release blocker | Keywords: | |
Cc: | Triage Stage: | Accepted | |
Has patch: | no | Needs documentation: | no |
Needs tests: | no | Patch needs improvement: | no |
Easy pickings: | no | UI/UX: | no |
Description
After upgrading from 1.5 to 1.6, my Django application running on Apache with mod_wsgi was unable to access environment variables set by Apache using SetEnv
and SetEnvIf
. Using Django 1.5, I was able to access this using the following wsgi.py (edited for brevity):
import os from django.core.wsgi import get_wsgi_application _application = get_wsgi_application() def application(environ, start_response): os.environ['MY_SETTING'] = environ['MY_SETTING'] return _application(environ, start_response)
Then, in settings.py, I would access MY_SETTING
using os.environ['MY_SETTING']
. After upgrading, I had to change the file to the following:
import os _application = None def application(environ, start_response): os.environ['MY_SETTING'] = environ['MY_SETTING'] global _application if _application is None: from django.core.wsgi import get_wsgi_application _application = get_wsgi_application() return _application(environ, start_response)
It appears that importing (and callling?) get_wsgi_application()
kicks off a chain of imports that will eventually import settings.py
. But, as the OS environment variables aren't set yet, settings.py can't access these environment variables properly.
I am not sure if this is considered a bug, but the backwards incompatible change certainly surprised me. If there is a better way to approach this same problem, I'd be happy to hear it.
Change History (6)
comment:1 by , 11 years ago
comment:2 by , 11 years ago
Severity: | Normal → Release blocker |
---|---|
Triage Stage: | Unreviewed → Accepted |
I can confirm that. The commit which triggered the settings import is [ac37ed21b3d66dd], which imports django.db.connections/transaction
in django/core/handlers/base.py
.
We can act at different levels:
- Amend the aforementioned commit to import connections/transaction in the
make_view_atomic
method. - Condition access of settings.DEBUG in signal connect method only if settings are already configured (
if settings.configured and settings.DEBUG
).
For me, the second option is much preferable, as it generally enables to connect signals without triggering settings configuration. And it does not change the behaviour when running runserver
as settings are configured sooner in any case with runserver
.
Could you please test this patch:
diff --git a/django/dispatch/dispatcher.py b/django/dispatch/dispatcher.py index a8cdc93..d26433a 100644 --- a/django/dispatch/dispatcher.py +++ b/django/dispatch/dispatcher.py @@ -85,7 +85,7 @@ class Signal(object): from django.conf import settings # If DEBUG is on, check that we got a good receiver - if settings.DEBUG: + if settings.configured and settings.DEBUG: import inspect assert callable(receiver), "Signal receivers must be callable."
comment:4 by , 11 years ago
I have no idea how I can avoid introducing such problems inadvertently in the future :(
comment:5 by , 11 years ago
Resolution: | → fixed |
---|---|
Status: | new → closed |
Here is a discussion on django-users raising this issue and how it affected some projects.