[Django] #25203: Document changes to WSGI application loading sequence

11 views
Skip to first unread message

Django

unread,
Jul 31, 2015, 12:11:02 PM7/31/15
to django-...@googlegroups.com
#25203: Document changes to WSGI application loading sequence
------------------------------+--------------------------------------------
Reporter: yscumc | Owner: nobody
Type: | Status: new
Uncategorized |
Component: | Version: 1.7
Uncategorized |
Severity: Normal | Keywords: wsgi setup application loading
Triage Stage: Unreviewed | Has patch: 0
Easy pickings: 0 | UI/UX: 0
------------------------------+--------------------------------------------
After upgrading Django from 1.6 to 1.7, I found that there were some
undocumented differences in how the wsgi loading is handled.

I had the following in Django 1.6 in my wsgi.py:

{{{
from django.core.wsgi import get_wsgi_application
_application = get_wsgi_application()

# Update DJANGO_SETTINGS_MODULE os env variable from internal Apache env
variable, set by "SetEnv" in httpd.conf
def application(environ, start_response):
if 'DJANGO_SETTINGS_MODULE' in environ:
os.environ['DJANGO_SETTINGS_MODULE'] =
environ['DJANGO_SETTINGS_MODULE']

return _application(environ, start_response)
}}}

This will get the env from the Apache conf and set it before a request to
make sure that the proper settings file is loaded.

However, in Django 1.7, this broke because `django.setup()` is now run as
part of `django.core.wsgi.get_wsgi_application()` and this causes the
settings file to be loaded before the first `application()` call (first
request).

Previously, the loading of the settings file seems to happen with the
first `application()` call, `django.core.wsgi.get_wsgi_application()()`.


Debugging this was actually more difficult than it seems. I initially just
got a 400 BAD REQUEST error after upgrading, with no errors in the logs.
It took a long time to realize my my custom settings file wasn't being
loaded and so `ALLOWED_HOSTS` weren't being loaded either.

After finding out it was a changed behavior in wsgi loading that was
causing the problem, fixing the problem was straightforward, but I
recommend updating the documentation with this change in Django 1.7 so
that others wouldn't run into this issue.


Here's the fixed version that also works with 1.7 (and earlier) if someone
is interested:

{{{
# Update DJANGO_SETTINGS_MODULE os env variable from internal Apache env
variable, set by "SetEnv" in httpd.conf
def application(environ, start_response):
if 'DJANGO_SETTINGS_MODULE' in environ:
os.environ['DJANGO_SETTINGS_MODULE'] =
environ['DJANGO_SETTINGS_MODULE']

# Only attempt to execute get_wsgi_application() once
if not application._app:
application._app = get_wsgi_application()

return application._app(environ, start_response)
application._app = None
}}}

--
Ticket URL: <https://code.djangoproject.com/ticket/25203>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.

Django

unread,
Jul 31, 2015, 12:36:42 PM7/31/15
to django-...@googlegroups.com
#25203: Document changes to WSGI application loading sequence in 1.7
-------------------------------------+-------------------------------------

Reporter: yscumc | Owner: nobody
Type: | Status: new
Cleanup/optimization |
Component: Documentation | Version: 1.7
Severity: Normal | Resolution:
Keywords: wsgi setup | Triage Stage: Accepted
application loading |
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0

Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Changes (by timgraham):

* needs_better_patch: => 0
* component: Uncategorized => Documentation
* needs_tests: => 0
* needs_docs: => 0
* type: Uncategorized => Cleanup/optimization
* stage: Unreviewed => Accepted


Comment:

If you could propose a patch, I'll be happy to review it.

--
Ticket URL: <https://code.djangoproject.com/ticket/25203#comment:1>

Django

unread,
Sep 11, 2015, 12:43:51 PM9/11/15
to django-...@googlegroups.com
#25203: Document changes to WSGI application loading sequence in 1.7
-------------------------------------+-------------------------------------

Reporter: yscumc | Owner: nobody
Type: | Status: new
Cleanup/optimization |
Component: Documentation | Version: 1.7
Severity: Normal | Resolution:
Keywords: wsgi setup | Triage Stage: Accepted
application loading |
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0

Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------

Comment (by paulrentschler):

I ran into this problem as well and created a pull request
(https://github.com/django/django/pull/5271) to address the issue.
Although I realize I didn't address the original submitter's request for
documentation about how wsgi loading is handled, I did provide changes to
the documentation at explains and provides a working solution that is also
backwards compatible for doing what the original submitter was trying to
do along with showing how to pass arbitrary variables from the Apache
configuration to Django.

--
Ticket URL: <https://code.djangoproject.com/ticket/25203#comment:2>

Django

unread,
Sep 11, 2015, 12:44:24 PM9/11/15
to django-...@googlegroups.com
#25203: Document changes to WSGI application loading sequence in 1.7
-------------------------------------+-------------------------------------

Reporter: yscumc | Owner: nobody
Type: | Status: new
Cleanup/optimization |
Component: Documentation | Version: 1.7
Severity: Normal | Resolution:
Keywords: wsgi setup | Triage Stage: Accepted
application loading |
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0

Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Changes (by paulrentschler):

* cc: paul@… (added)


--
Ticket URL: <https://code.djangoproject.com/ticket/25203#comment:3>

Django

unread,
Sep 11, 2015, 1:24:09 PM9/11/15
to django-...@googlegroups.com
#25203: Document changes to WSGI application loading sequence in 1.7
-------------------------------------+-------------------------------------
Reporter: yscumc | Owner: nobody
Type: | Status: closed

Cleanup/optimization |
Component: Documentation | Version: 1.7
Severity: Normal | Resolution: fixed

Keywords: wsgi setup | Triage Stage: Accepted
application loading |
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0

Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Changes (by Tim Graham <timograham@…>):

* status: new => closed
* resolution: => fixed


Comment:

In [changeset:"47016d4322574860f90431e1c87d19f7a1f778c6" 47016d4]:
{{{
#!CommitTicketReference repository=""
revision="47016d4322574860f90431e1c87d19f7a1f778c6"
Fixed #25203 -- Documented how to pass Apache environment variables to
Django.
}}}

--
Ticket URL: <https://code.djangoproject.com/ticket/25203#comment:4>

Django

unread,
Sep 11, 2015, 1:24:49 PM9/11/15
to django-...@googlegroups.com
#25203: Document changes to WSGI application loading sequence in 1.7
-------------------------------------+-------------------------------------
Reporter: yscumc | Owner: nobody

Type: | Status: closed
Cleanup/optimization |
Component: Documentation | Version: 1.7
Severity: Normal | Resolution: fixed
Keywords: wsgi setup | Triage Stage: Accepted
application loading |
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0

Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------

Comment (by Tim Graham <timograham@…>):

In [changeset:"c8773493b62083b9ca5476a6040737f5cca79944" c877349]:
{{{
#!CommitTicketReference repository=""
revision="c8773493b62083b9ca5476a6040737f5cca79944"
[1.8.x] Fixed #25203 -- Documented how to pass Apache environment
variables to Django.

Backport of 47016d4322574860f90431e1c87d19f7a1f778c6 from master
}}}

--
Ticket URL: <https://code.djangoproject.com/ticket/25203#comment:5>

Django

unread,
Sep 11, 2015, 6:12:13 PM9/11/15
to django-...@googlegroups.com
#25203: Document changes to WSGI application loading sequence in 1.7
-------------------------------------+-------------------------------------
Reporter: yscumc | Owner: nobody

Type: | Status: closed
Cleanup/optimization |
Component: Documentation | Version: 1.7
Severity: Normal | Resolution: fixed
Keywords: wsgi setup | Triage Stage: Accepted
application loading |
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0

Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------

Comment (by carljm):

Commented on the PR here:
https://github.com/django/django/commit/47016d4322574860f90431e1c87d19f7a1f778c6#commitcomment-13192876

I'm not convinced this is a technique that the Django documentation should
promote.

--
Ticket URL: <https://code.djangoproject.com/ticket/25203#comment:6>

Django

unread,
Sep 13, 2015, 1:09:24 AM9/13/15
to django-...@googlegroups.com
#25203: Document changes to WSGI application loading sequence in 1.7
-------------------------------------+-------------------------------------

Reporter: yscumc | Owner: nobody
Type: | Status: new
Cleanup/optimization |
Component: Documentation | Version: 1.7
Severity: Normal | Resolution:
Keywords: wsgi setup | Triage Stage: Accepted
application loading |
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0

Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Changes (by carljm):

* status: closed => new
* resolution: fixed =>


Comment:

Graham Dumpleton (author of mod_wsgi) has confirmed that this is not a
technique we should be recommending in our docs:
https://twitter.com/GrahamDumpleton/status/642714837466906624

He says once he is back from vacation he will recommend better
alternatives that we could document.

I think we should roll back this patch and wait for his recommendation.

--
Ticket URL: <https://code.djangoproject.com/ticket/25203#comment:7>

Django

unread,
Sep 14, 2015, 2:12:59 PM9/14/15
to django-...@googlegroups.com
#25203: Document changes to WSGI application loading sequence in 1.7
-------------------------------------+-------------------------------------
Reporter: yscumc | Owner: nobody
Type: | Status: closed

Cleanup/optimization |
Component: Documentation | Version: 1.7
Severity: Normal | Resolution: fixed

Keywords: wsgi setup | Triage Stage: Accepted
application loading |
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0

Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Changes (by Tim Graham <timograham@…>):

* status: new => closed
* resolution: => fixed


Comment:

In [changeset:"83ea3bc798a87098e6507450e7db610020eb215e" 83ea3bc7]:
{{{
#!CommitTicketReference repository=""
revision="83ea3bc798a87098e6507450e7db610020eb215e"
Reverted "Fixed #25203 -- Documented how to pass Apache environment
variables to Django."

As discussed on the ticket, this isn't a pattern we should recommend.

This reverts commit 47016d4322574860f90431e1c87d19f7a1f778c6.
}}}

--
Ticket URL: <https://code.djangoproject.com/ticket/25203#comment:8>

Django

unread,
Sep 14, 2015, 2:15:47 PM9/14/15
to django-...@googlegroups.com
#25203: Document changes to WSGI application loading sequence in 1.7
-------------------------------------+-------------------------------------
Reporter: yscumc | Owner: nobody

Type: | Status: closed
Cleanup/optimization |
Component: Documentation | Version: 1.7
Severity: Normal | Resolution: fixed
Keywords: wsgi setup | Triage Stage: Accepted
application loading |
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0

Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------

Comment (by Tim Graham <timograham@…>):

In [changeset:"d0d25671207bd421adff1dd88605e93ffc00f51f" d0d2567]:
{{{
#!CommitTicketReference repository=""
revision="d0d25671207bd421adff1dd88605e93ffc00f51f"
[1.8.x] Reverted "Fixed #25203 -- Documented how to pass Apache
environment variables to Django."

As discussed on the ticket, this isn't a pattern we should recommend.

This reverts commit c8773493b62083b9ca5476a6040737f5cca79944.
}}}

--
Ticket URL: <https://code.djangoproject.com/ticket/25203#comment:9>

Django

unread,
Sep 14, 2015, 2:16:12 PM9/14/15
to django-...@googlegroups.com
#25203: Document changes to WSGI application loading sequence in 1.7
-------------------------------------+-------------------------------------

Reporter: yscumc | Owner: nobody
Type: | Status: new
Cleanup/optimization |
Component: Documentation | Version: 1.7
Severity: Normal | Resolution:
Keywords: wsgi setup | Triage Stage: Accepted
application loading |
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0

Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Changes (by timgraham):

* status: closed => new
* resolution: fixed =>


--
Ticket URL: <https://code.djangoproject.com/ticket/25203#comment:10>

Django

unread,
Sep 29, 2015, 6:27:09 AM9/29/15
to django-...@googlegroups.com
#25203: Document changes to WSGI application loading sequence in 1.7
-------------------------------------+-------------------------------------

Reporter: yscumc | Owner: nobody
Type: | Status: new
Cleanup/optimization |
Component: Documentation | Version: 1.7
Severity: Normal | Resolution:
Keywords: wsgi setup | Triage Stage: Accepted
application loading |
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0

Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------

Comment (by grahamd):

Where you need a process level global variable inherited from some key set
in the Apache configuration, what you are best to do is ensure you are
running the Django application in a mod_wsgi daemon process group of its
own (forced to use main interpreter application group), and then base any
in code decisions on the name of the daemon process group you used in the
Apache configuration.

For example, you could even have the name of the Django settings module be
the name of the daemon process group.

{{{
WSGIDaemonProcess mysite.production.settings
WSGIScriptAlias / /some/path/wsgi.py process-
group=mysite.production.settings application-group=%{GLOBAL}
}}}

In the `wsgi.py` file you can then say:

{{{
try:
import mod_wsgi
os.environ['DJANGO_SETTINGS_MODULE'] = mod_wsgi.process_group
except ImportError:
os.environ.setdefault('DJANGO_SETTINGS_MODULE',
'mysite.development.settings')
}}}

This can be placed before any other module imports as it is dependent on
information available at import time and not at the time of a request.

--
Ticket URL: <https://code.djangoproject.com/ticket/25203#comment:11>

Django

unread,
Oct 24, 2015, 11:14:38 AM10/24/15
to django-...@googlegroups.com
#25203: Document changes to WSGI application loading sequence in 1.7
-------------------------------------+-------------------------------------

Reporter: yscumc | Owner: nobody
Type: | Status: new
Cleanup/optimization |
Component: Documentation | Version: 1.7
Severity: Normal | Resolution:
Keywords: wsgi setup | Triage Stage: Accepted
application loading |
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0

Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Changes (by jdufresne):

* cc: jon.dufresne@… (added)


Comment:

FWIW, this unexpected change has occurred in a previous Django release as
well. See ticket #21486. The response in that ticket was to avoid
importing {{{settings.py}}} during a call to {{{get_wsgi_application()}}}
such that the original pattern would continue to work. I'm not sure if
this is still feasible today.

I appreciate the expertise and knowledge Graham Dumpleton brings to the
table. But it feels a tad limiting that one can't freely pass an arbitrary
amount of environment variables from Apache to Django. Some deployment
strategies, such as Twelve-Factor App (Not Django specific
http://12factor.net/config) specifically recommend configuring web apps
through environment variables. Is using environment variables really just
not possible with mod_wsgi?

If my application has exactly one variable to read, it is difficult to
make multiple decisions on this. For example, my application loads
settings slightly differently in production vs debug/development mode.
This is to ease configuration for other, perhaps new, developers. With
just one available variable that is '''always''' set it becomes difficult
to do this.

--
Ticket URL: <https://code.djangoproject.com/ticket/25203#comment:12>

Reply all
Reply to author
Forward
0 new messages