Opened 6 years ago

Closed 6 years ago

Last modified 6 years ago

#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 Changed 6 years ago by Jon Dufresne

Here is a discussion on django-users raising this issue and how it affected some projects.

comment:2 Changed 6 years ago by Claude Paroz

Severity: NormalRelease blocker
Triage Stage: UnreviewedAccepted

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:

  1. Amend the aforementioned commit to import connections/transaction in the make_view_atomic method.
  2. 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:3 Changed 6 years ago by Jon Dufresne

Could you please test this patch:

Yup, that works.

comment:4 Changed 6 years ago by Aymeric Augustin

I have no idea how I can avoid introducing such problems inadvertently in the future :(

comment:5 Changed 6 years ago by Claude Paroz <claude@…>

Resolution: fixed
Status: newclosed

In 42fef2944640659b95679381a9c8f02b3be884b1:

Fixed #21486 -- Prevented settings config in signal connection

This was particularly problematic in the chain get_wsgi_application
-> db.connections import -> signal connection -> settings configuration.
Thanks Jon Dufresne for the report.

comment:6 Changed 6 years ago by Claude Paroz <claude@…>

In 432de546113942be60089a879371073ad09fb4fe:

[1.6.x] Fixed #21486 -- Prevented settings config in signal connection

This was particularly problematic in the chain get_wsgi_application
-> db.connections import -> signal connection -> settings configuration.
Thanks Jon Dufresne for the report.
Backport of 42fef294464 from master.

Note: See TracTickets for help on using tickets.
Back to Top