The global state problem is something that's been bothering me for a long
while, but after seeing a presentation of Alex Gaynor [1] from last year, I
started thinking about this again.
The main problem is that you'd need to have a DjangoProject object which
contains the root configuration and you'd have to somehow pass that object
around everywhere.
Maybe I'm not the first to think about this, but what's wrong with
thread-local-storage? In Django, we have a huge advantage above nodejs in
that there's only one active request per thread and that request should
belong to only one DjangoProject instance. (We don't have unexpected
contextswitches in the same thread, like in Twisted or Tulip. -- We can
make that assumption.)
Actually we are already using threadlocals for the current active language
[2], so I don't see any reason for not using the same approach to keep
track of the currently active DjangoApplication object.
It's not a really small project, but not impossible huge either. The most
important parts of the code that need to be changed to use this thread
local are:
* django.conf.settings:
We don't want to break that API, so the settings object should become a
proxy that knows the current active project and returns the correct
settings.
* the reverse() functions (and a few others) from URL patterns.
URL patterns depend on the application.
* Django models:
That's the harder one. MyModel.objects.get() needs to know the settings, in
order to know what the current database is.
I would propose a python context manager to move from one project to
another, if you ever have to. Say that you want to query a model from
another project, you can do this:
other_django_project = DjangoProject.from_settings_file(my_project_settings)
with other_django_project.activate():
MyModel.objects.get()
manage.py should look like this:
if __name__ == '__main__':
django_project = DjangoProject.from_settings_file(my_project_settings)
with django_project.activate():
execute_from_command_line(sys.argv)
And for the flask-lovers which don't like automatic code generation and
singleton patterns, they can just use the DangoProject constructor:
if __name__ == '__main__':
django_project = DjangoProject(
url_patterns=root_url_patterns,
installed_apps=[ ... ],
....
)
with django_project.activate():
execute_from_command_line(sys.argv)
For the why of all this, I refer to the presentation of Alex, but the main
advantages are that it becomes much more easy to integrate Django projects
in other Python projects and that unit testing becomes easier: you don't
have a global state.
What do you think? I don't see real backward-compatibility issues that we
can't solve. Do I forget something?
Cheers,
Jonathan
[1] https://www.youtube.com/watch?v=0FD510Oz2e4
[2]
https://github.com/django/django/blob/master/django/utils/translation/trans_real.py#L23
--
You received this message because you are subscribed to the Google Groups
"Django developers" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To post to this group, send email to [email protected].
Visit this group at http://groups.google.com/group/django-developers.
To view this discussion on the web visit
https://groups.google.com/d/msgid/django-developers/7dd166af-f8d6-4838-9a34-480ef5e5581c%40googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.