How to get multiple Django instances in PyISAPIe and elsewhere

21 views
Skip to first unread message

Phillip

unread,
May 29, 2008, 4:38:49 PM5/29/08
to PyISAPIe
I don't know why I didn't think of this before, but it's easy enough
to hook os.environ to return varying values of DJANGO_SETTINGS_MODULE
based on, say, the current request URL.

I haven't tested this with PyISAPIe yet, but it looks like it will
work, even with other servers :)

I'm not sure if Django does any global stuff- if so, there might still
be problems.

I've also posted this code on the group page under HookEnv.py and
hopefully anyone with time to test it can provide some feedback. I
just wanted to get the idea out ASAP.

- Phillip

---------->


from Http import Env
import os

DjangoMap = {
"/django/app1" : "app1.settings",
"/django/app2" : "app2.settings"
}

class Hook(dict):
Var = "DJANGO_SETTINGS_MODULE"

def __init__(This):
This.update(os.environ)

def __contains__(This, Name):
if Name == This.Var:
return True

return dict.__contains__(This, Name)

def __getitem__(This, Name):
if Name != This.Var:
return dict.__getitem__(This, Name)

Script = Env.SCRIPT_NAME

for Item in DjangoMap:
if Script.startswith(Item):
return DjangoMap[Item]

def __setitem__(This, Name, Value):
raise NotImplementedError, "os.environ not available for writing"


os.environ = Hook()

rcs_comp

unread,
May 30, 2008, 11:28:31 AM5/30/08
to PyISAPIe
Phillip,

Thanks for your work on this. Unfortunately, as described below, its
not just the DJANGO_SETTINGS_MODULE that is the problem.

My lack of experience in Python is going to become apparent really
quick, so I hope you will be forgiving. I managed to make a small
change in the Django source when running Django with a WSGI handler
that allowed me to switch the configuration module per-request. While
it worked with respect to getting the settings to be picked up per-
request, it seemed to introduce some other problems.

You can take a look at what I did by downloading:

http://groups.google.com/group/pyisapie/web/multiple_django.zip

and then:

1) run `python wsgi_server.py`

You should now be able to browse to:

1) http://localhost:8000/dgtutorial/polls.py
2) http://localhost:8000/dgtutorial2/polls.py

Notice that the second request fails because it is running off
dgtutorial's settings module (and not dgtutorial2's settings module).
This is because Django only picks up the settings module once (i.e.
per python process load), not on each request.

Now, apply the patch included in the zip file above. It forces the
settings module to be reassigned on every WSGI request instead of on a
per-process initialization (in django.conf.__init__.py). This
accomplishes the short-term goal of getting the settings modules
assigned according to the request. You should now be able to browse
again to:

1) http://localhost:8000/dgtutorial/polls.py
2) http://localhost:8000/dgtutorial2/polls.py

The output tells us two things:

1) The appropriate settings modules for the different projects are
being assigned to Django based on the URL requested.
2) Django is relying on a process-level (not thread level)
configuration value somewhere which is causing our static template
output to be cached and used from the wrong project (that is why you
see "project (static value): dgtutorial" at the top of the output for
dgtutorial2"). If you stop the server (CTRL+BREAK) and restart it and
browse to the second url first and then the first, it proves the
output has been cached somehow.

So, this leads me to the following *unsubstantiated* conclusion: that
there are numerous places where the Django core is assuming that only
one project will be run concurrently in each process and there are a
lot of settings and values stored at the process level instead of the
thread level. I began to hunt for those instances when it dawned on
me that the above patch was probably not thread safe. Rather than
storing the settings in django.conf.settings, they probably need to be
stored in some kind of per-thread scoped variable. Unfortunately, I
am now completely out of my area of expertise and would appreciate
some comments from others who have more experience in this area.

I am also going to post this thread on the Django-dev group and hope
for some knowledgeable answers.
Reply all
Reply to author
Forward
0 new messages