Automatically get default value for "current_app", for easier namespace support.

238 views
Skip to first unread message

Tai Lee

unread,
May 20, 2014, 4:01:55 AM5/20/14
to django-d...@googlegroups.com
Right now it seems that for a generic app to support the possibility of being installed in a URLconf with a namespace, the app author will need to take care to explicitly define a `current_app` for every call to `reverse()`, `TemplateResponse`, `RequestContext`, `Context` and `{% url %}`.

Django already adds a `ResolverMatch` object to every request. Shouldn't Django just use this to get a default value for "current_app", whenever users don't explicitly define one?

This should make it almost a non-issue to define the current app for every case except explicit calls to `reverse()`, `Context` and templates that are rendered without a `RequestContext` object (as none of these have access to the request).

We could even get a sensible default in those cases as well by storing the current app in thread local storage, and using that as a default in `reverse()`.

I've made a ticket for this, but it was closed as wontfix because thread local storage is global state and Django is at war with global state.


As suggested, I'm bringing this to django-developers to ask for any alternative suggestions that don't involve global state, and also to try and make my case for the ticket as originally described.

Django already uses `threading.local()` in a number of places such as `urlresolvers._prefixes`, `urlresolvers._urlconfs`, `CacheHandler._caches`, `ConnectionHandler._connections`, `trans_real._active`, `timezone._active`.

The most notably similar use case is probably for timezone support, which allows users to call `activate()` to tell Django what timezone they are in, and then other parts of the code call `get_current_timezone()` to get the value stored in thread local storage.

I think it would be along the same lines to have the ability to set a current app and have other parts of the code get the current app, without having to pass an object around as an argument every step of the way, which is practically impossible.

For example, models with a `get_absolute_url` method (or perhaps multiple `get_foo_url` methods) that are rendered in templates. These functions can't take arguments when rendered as context variables in a template, and have no way to obtain the current namespace from the `request` object.

This would make it super easy for users (via middleware) or Django itself to inspect the `request.resolver_match` object and set the current app early in the request/response cycle, and then `reverse()` and `{% url %}` would just work without generic app authors having to explicitly build in support for multiple instances of their app being deployed within a single project.

Does anyone else think this would be a good idea, or does anyone have an alternative suggestion?

Cheers.
Tai.

George Ma

unread,
Oct 26, 2015, 12:44:31 AM10/26/15
to Django developers (Contributions to Django itself)
That's exactly what I'm thinking about. Unfortunately, it's not brought to the attention among Django developers so far.

Marten Kenbeek

unread,
Oct 26, 2015, 8:15:26 AM10/26/15
to Django developers (Contributions to Django itself)
Hi George,

The behaviour for {% url %} has since been changed when used with 
a RequestContext. It will now default to the current namespace when 
one is available. This change will be available in 1.9. 

This change doesn't cover the thread-local storage for calls to reverse(), 
or for {% url %} without a RequestContext. That is still marked as wont-fix. 

Marten
Reply all
Reply to author
Forward
0 new messages