mirror of https://github.com/django/django.git
Fixed #24904 -- Fixed nested namespaces in current_app.
Fixed reverse() to correctly handled nested namespace lookups in current_app.
This commit is contained in:
parent
6b41834855
commit
f0450c9b12
|
@ -549,19 +549,26 @@ def reverse(viewname, urlconf=None, args=None, kwargs=None, current_app=None):
|
||||||
view = parts[0]
|
view = parts[0]
|
||||||
path = parts[1:]
|
path = parts[1:]
|
||||||
|
|
||||||
|
if current_app:
|
||||||
|
current_path = current_app.split(':')
|
||||||
|
current_path.reverse()
|
||||||
|
else:
|
||||||
|
current_path = None
|
||||||
|
|
||||||
resolved_path = []
|
resolved_path = []
|
||||||
ns_pattern = ''
|
ns_pattern = ''
|
||||||
while path:
|
while path:
|
||||||
ns = path.pop()
|
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
|
# Lookup the name to see if it could be an app identifier
|
||||||
try:
|
try:
|
||||||
app_list = resolver.app_dict[ns]
|
app_list = resolver.app_dict[ns]
|
||||||
# Yes! Path part matches an app in the current Resolver
|
# 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,
|
# If we are reversing for a particular app,
|
||||||
# use that namespace
|
# use that namespace
|
||||||
ns = current_app
|
ns = current_ns
|
||||||
elif ns not in app_list:
|
elif ns not in app_list:
|
||||||
# The name isn't shared by one of the instances
|
# The name isn't shared by one of the instances
|
||||||
# (i.e., the default) so just pick the first instance
|
# (i.e., the default) so just pick the first instance
|
||||||
|
@ -570,6 +577,9 @@ def reverse(viewname, urlconf=None, args=None, kwargs=None, current_app=None):
|
||||||
except KeyError:
|
except KeyError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
if ns != current_ns:
|
||||||
|
current_path = None
|
||||||
|
|
||||||
try:
|
try:
|
||||||
extra, resolver = resolver.namespace_dict[ns]
|
extra, resolver = resolver.namespace_dict[ns]
|
||||||
resolved_path.append(ns)
|
resolved_path.append(ns)
|
||||||
|
|
|
@ -7,6 +7,7 @@ from .namespace_urls import URLObject
|
||||||
from .views import view_class_instance
|
from .views import view_class_instance
|
||||||
|
|
||||||
testobj3 = URLObject('testapp', 'test-ns3')
|
testobj3 = URLObject('testapp', 'test-ns3')
|
||||||
|
testobj4 = URLObject('testapp', 'test-ns4')
|
||||||
|
|
||||||
# test deprecated patterns() function. convert to list of urls() in Django 2.0
|
# test deprecated patterns() function. convert to list of urls() in Django 2.0
|
||||||
with warnings.catch_warnings():
|
with warnings.catch_warnings():
|
||||||
|
@ -24,6 +25,7 @@ with warnings.catch_warnings():
|
||||||
url(r'^view_class/(?P<arg1>[0-9]+)/(?P<arg2>[0-9]+)/$', view_class_instance, name='inc-view-class'),
|
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'^test3/', include(testobj3.urls)),
|
||||||
|
(r'^test4/', include(testobj4.urls)),
|
||||||
(r'^ns-included3/', include('urlpatterns_reverse.included_urls', namespace='inc-ns3')),
|
(r'^ns-included3/', include('urlpatterns_reverse.included_urls', namespace='inc-ns3')),
|
||||||
(r'^ns-included4/', include('urlpatterns_reverse.namespace_urls', namespace='inc-ns4')),
|
(r'^ns-included4/', include('urlpatterns_reverse.namespace_urls', namespace='inc-ns4')),
|
||||||
)
|
)
|
||||||
|
|
|
@ -574,6 +574,53 @@ class NamespaceTests(SimpleTestCase):
|
||||||
self.assertEqual('/inc70/', reverse('inc-ns5:inner-nothing', args=['70']))
|
self.assertEqual('/inc70/', reverse('inc-ns5:inner-nothing', args=['70']))
|
||||||
self.assertEqual('/inc78/extra/foobar/', reverse('inc-ns5:inner-extra', args=['78', 'foobar']))
|
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 (#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__)
|
@override_settings(ROOT_URLCONF=urlconf_outer.__name__)
|
||||||
class RequestURLconfTests(SimpleTestCase):
|
class RequestURLconfTests(SimpleTestCase):
|
||||||
|
|
Loading…
Reference in New Issue