#17914: reverse() does not support namespaced view references -------------------------------------------------+-------------------- Reporter: Bradley Ayers <bradley.ayers@…> | Owner: nobody Type: Bug | Status: new Component: Core (URLs) | Version: 1.3 Severity: Normal | Keywords: Triage Stage: Unreviewed | Has patch: 0 Easy pickings: 0 | UI/UX: 0 -------------------------------------------------+-------------------- 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")) ) }}} Removing ``, namespace="foo"`` will make it work. My understanding of why this happens, is that `reverse()` traverses `RegexURLResolver`s *only* for strings. Function references are passed directly to the root `RegexURLResolver.reverse` method.: {{{ # 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 `RegexURLResolver`'s `reverse_dict` dictionary. Populating `reverse_dict` is lazy and happens on first access, the work is performed in `RegexURLResolver._populate`: {{{ # 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 `RegexURLResolver._populate` and `reverse()` leads to the problem. -- Ticket URL: <https://code.djangoproject.com/ticket/17914> Django <https://code.djangoproject.com/> The Web framework for perfectionists with deadlines. -- You received this message because you are subscribed to the Google Groups "Django updates" group. To post to this group, send email to django-updates@googlegroups.com. To unsubscribe from this group, send email to django-updates+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/django-updates?hl=en.