Add support for namespaced view references when passing a callable to reverse()
|Reported by:||Owned by:||nobody|
|Cc:||bradley.ayers@…, amirouche.boubekki@…, gwahl@…, Florian Apolloner||Triage Stage:||Accepted|
|Has patch:||yes||Needs documentation:||no|
|Needs tests:||no||Patch needs improvement:||no|
It's not possible to reverse a URL by passing a function reference to reverse()
that's hooked into the URLconf under a namespace.
Consider the trivial Django project (that doesn't work):
# urls.py from django.conf.urls.defaults import patterns, include from django.core.urlresolvers import reverse from django.http import HttpResponse def view(request): # Return the URL to this view return HttpResponse(reverse(view)) level2 = patterns('', (r'^2/', view) ) urlpatterns = patterns('', (r'^1/', include(level2, namespace="foo")) )
will make it work.
My understanding of why this happens, is that
*only* for strings. Function references are passed directly to the root
# from django/core/urlresolvers.py ~ line 432 if not isinstance(viewname, basestring): view = viewname else: # <snip> -- resolver traversal happens here to honor namespaces # `resolver` is reassigned to last RegexURLResolver in namespace chain return iri_to_uri(resolver._reverse_with_prefix(view, prefix, *args, **kwargs))
Obviously traversing namespaces isn't possible for a function reference,
so what's needed is to add *all* descendent view references into each
reverse_dict is lazy and happens on first access, the work is
# django/core/urlresolvers.py ~ line 237 def _populate(self): # <snip> for pattern in reversed(self.url_patterns): # <snip> if isinstance(pattern, RegexURLResolver): if pattern.namespace: # <snip> -- tldr `self.reverse_dict` isn't populated, `pattern` (the # RegexURLResolver) is instead stored in `self.namespace_dict` else: # <snip> -- tldr `self.reverse_dict` *is* populated with the keys # being the name of each URL (or the function reference) # defined in this level. (i.e. only children, not all descendants) else: # <snip> -- tldr `self.reverse_dict` is again populated
This combination of behaviour by
leads to the problem.
Change History (26)
comment:18 Changed 17 months ago by
|Summary:||reverse() does not support namespaced view references → reverse() does not support namespaced view references when passed a callable|