Skip to content

Commit

Permalink
Fixed #24904 -- Fixed nested namespaces in current_app.
Browse files Browse the repository at this point in the history
Fixed reverse() to correctly handled nested namespace lookups
in current_app.
  • Loading branch information
knbk committed Jun 3, 2015
1 parent 7c637a3 commit 1445dac
Show file tree
Hide file tree
Showing 4 changed files with 35 additions and 3 deletions.
14 changes: 11 additions & 3 deletions django/core/urlresolvers.py
Expand Up @@ -549,26 +549,34 @@ def reverse(viewname, urlconf=None, args=None, kwargs=None, current_app=None):
view = parts[0]
path = parts[1:]

if current_app:
current_path = current_app.split(':')
current_path.reverse()
else:
current_path = None

resolved_path = []
ns_pattern = ''
while path:
ns = path.pop()
current_ns = current_path.pop() if current_path else None

# Lookup the name to see if it could be an app identifier
try:
app_list = resolver.app_dict[ns]
# Yes! Path part matches an app in the current Resolver
if current_app and current_app in app_list:
if current_ns and current_ns in app_list:
# If we are reversing for a particular app,
# use that namespace
ns = current_app
ns = current_ns
elif ns not in app_list:
# The name isn't shared by one of the instances
# (i.e., the default) so just pick the first instance
# as the default.
ns = app_list[0]
current_path = None
except KeyError:
pass
current_path = None

try:
extra, resolver = resolver.namespace_dict[ns]
Expand Down
3 changes: 3 additions & 0 deletions docs/releases/1.8.3.txt
Expand Up @@ -50,3 +50,6 @@ Bugfixes

* Fixed recording of applied status for squashed (replacement) migrations
(:ticket:`24628`).

* Fixed :func:`~django.core.urlresolvers.reverse()` not handling nested
namespaces in the ``current_app`` parameter (:ticket:`24904`).
2 changes: 2 additions & 0 deletions tests/urlpatterns_reverse/included_namespace_urls.py
Expand Up @@ -7,6 +7,7 @@
from .views import view_class_instance

testobj3 = URLObject('testapp', 'test-ns3')
testobj4 = URLObject('testapp', 'test-ns4')

# test deprecated patterns() function. convert to list of urls() in Django 2.0
with warnings.catch_warnings():
Expand All @@ -24,6 +25,7 @@
url(r'^view_class/(?P<arg1>[0-9]+)/(?P<arg2>[0-9]+)/$', view_class_instance, name='inc-view-class'),

(r'^test3/', include(testobj3.urls)),
(r'^test4/', include(testobj4.urls)),
(r'^ns-included3/', include('urlpatterns_reverse.included_urls', namespace='inc-ns3')),
(r'^ns-included4/', include('urlpatterns_reverse.namespace_urls', namespace='inc-ns4')),
)
19 changes: 19 additions & 0 deletions tests/urlpatterns_reverse/tests.py
Expand Up @@ -574,6 +574,25 @@ def test_namespaces_with_variables(self):
self.assertEqual('/inc70/', reverse('inc-ns5:inner-nothing', args=['70']))
self.assertEqual('/inc78/extra/foobar/', reverse('inc-ns5:inner-extra', args=['78', 'foobar']))

def test_nested_app_lookup(self):
"A nested current_app should be split in individual namespaces: see #24904"
self.assertEqual('/ns-included1/test4/inner/', reverse('inc-ns1:testapp:urlobject-view'))
self.assertEqual('/ns-included1/test4/inner/37/42/', reverse('inc-ns1:testapp:urlobject-view', args=[37, 42]))
self.assertEqual('/ns-included1/test4/inner/42/37/', reverse('inc-ns1:testapp:urlobject-view', kwargs={'arg1': 42, 'arg2': 37}))
self.assertEqual('/ns-included1/test4/inner/+%5C$*/', reverse('inc-ns1:testapp:urlobject-special-view'))

self.assertEqual('/ns-included1/test3/inner/', reverse('inc-ns1:testapp:urlobject-view', current_app='inc-ns1:test-ns3'))
self.assertEqual('/ns-included1/test3/inner/37/42/', reverse('inc-ns1:testapp:urlobject-view', args=[37, 42], current_app='inc-ns1:test-ns3'))
self.assertEqual('/ns-included1/test3/inner/42/37/', reverse('inc-ns1:testapp:urlobject-view', kwargs={'arg1': 42, 'arg2': 37}, current_app='inc-ns1:test-ns3'))
self.assertEqual('/ns-included1/test3/inner/+%5C$*/', reverse('inc-ns1:testapp:urlobject-special-view', current_app='inc-ns1:test-ns3'))

def test_current_app_no_partial_match(self):
"current_app should either match the whole path or shouldn't be used"
self.assertEqual('/ns-included1/test4/inner/', reverse('inc-ns1:testapp:urlobject-view', current_app='non-existant:test-ns3'))
self.assertEqual('/ns-included1/test4/inner/37/42/', reverse('inc-ns1:testapp:urlobject-view', args=[37, 42], current_app='non-existant:test-ns3'))
self.assertEqual('/ns-included1/test4/inner/42/37/', reverse('inc-ns1:testapp:urlobject-view', kwargs={'arg1': 42, 'arg2': 37}, current_app='non-existant:test-ns3'))
self.assertEqual('/ns-included1/test4/inner/+%5C$*/', reverse('inc-ns1:testapp:urlobject-special-view', current_app='non-existant:test-ns3'))


@override_settings(ROOT_URLCONF=urlconf_outer.__name__)
class RequestURLconfTests(SimpleTestCase):
Expand Down

0 comments on commit 1445dac

Please sign in to comment.