summaryrefslogtreecommitdiff
path: root/tests/regressiontests/urlpatterns_reverse
diff options
context:
space:
mode:
authorRussell Keith-Magee <russell@keith-magee.com>2009-07-16 16:16:13 +0000
committerRussell Keith-Magee <russell@keith-magee.com>2009-07-16 16:16:13 +0000
commit8d48eaa064c88533be5082e3f45638fbd48491d8 (patch)
tree869920eb92a7e4b4248b3adf5e3f9104c4d57532 /tests/regressiontests/urlpatterns_reverse
parent9fd19c01611e5ed1ed64bbeb462ab96499d72a6c (diff)
Fixed #10061 -- Added namespacing for named URLs - most importantly, for the admin site, where the absence of this facility was causing problems. Thanks to the many people who contributed to and helped review this patch.
This change is backwards incompatible for anyone that is using the named URLs introduced in [9739]. Any usage of the old admin_XXX names need to be modified to use the new namespaced format; in many cases this will be as simple as a search & replace for "admin_" -> "admin:". See the docs for more details on the new URL names, and the namespace resolution strategy. git-svn-id: http://code.djangoproject.com/svn/django/trunk@11250 bcc190cf-cafb-0310-a4f2-bffc1f526a37
Diffstat (limited to 'tests/regressiontests/urlpatterns_reverse')
-rw-r--r--tests/regressiontests/urlpatterns_reverse/included_namespace_urls.py13
-rw-r--r--tests/regressiontests/urlpatterns_reverse/namespace_urls.py38
-rw-r--r--tests/regressiontests/urlpatterns_reverse/tests.py82
3 files changed, 132 insertions, 1 deletions
diff --git a/tests/regressiontests/urlpatterns_reverse/included_namespace_urls.py b/tests/regressiontests/urlpatterns_reverse/included_namespace_urls.py
new file mode 100644
index 0000000000..073190657c
--- /dev/null
+++ b/tests/regressiontests/urlpatterns_reverse/included_namespace_urls.py
@@ -0,0 +1,13 @@
+from django.conf.urls.defaults import *
+from namespace_urls import URLObject
+
+testobj3 = URLObject('testapp', 'test-ns3')
+
+urlpatterns = patterns('regressiontests.urlpatterns_reverse.views',
+ url(r'^normal/$', 'empty_view', name='inc-normal-view'),
+ url(r'^normal/(?P<arg1>\d+)/(?P<arg2>\d+)/$', 'empty_view', name='inc-normal-view'),
+
+ (r'^test3/', include(testobj3.urls)),
+ (r'^ns-included3/', include('regressiontests.urlpatterns_reverse.included_urls', namespace='inc-ns3')),
+)
+
diff --git a/tests/regressiontests/urlpatterns_reverse/namespace_urls.py b/tests/regressiontests/urlpatterns_reverse/namespace_urls.py
new file mode 100644
index 0000000000..27cc7f7a22
--- /dev/null
+++ b/tests/regressiontests/urlpatterns_reverse/namespace_urls.py
@@ -0,0 +1,38 @@
+from django.conf.urls.defaults import *
+
+class URLObject(object):
+ def __init__(self, app_name, namespace):
+ self.app_name = app_name
+ self.namespace = namespace
+
+ def urls(self):
+ return patterns('',
+ url(r'^inner/$', 'empty_view', name='urlobject-view'),
+ url(r'^inner/(?P<arg1>\d+)/(?P<arg2>\d+)/$', 'empty_view', name='urlobject-view'),
+ ), self.app_name, self.namespace
+ urls = property(urls)
+
+testobj1 = URLObject('testapp', 'test-ns1')
+testobj2 = URLObject('testapp', 'test-ns2')
+default_testobj = URLObject('testapp', 'testapp')
+
+otherobj1 = URLObject('nodefault', 'other-ns1')
+otherobj2 = URLObject('nodefault', 'other-ns2')
+
+urlpatterns = patterns('regressiontests.urlpatterns_reverse.views',
+ url(r'^normal/$', 'empty_view', name='normal-view'),
+ url(r'^normal/(?P<arg1>\d+)/(?P<arg2>\d+)/$', 'empty_view', name='normal-view'),
+
+ (r'^test1/', include(testobj1.urls)),
+ (r'^test2/', include(testobj2.urls)),
+ (r'^default/', include(default_testobj.urls)),
+
+ (r'^other1/', include(otherobj1.urls)),
+ (r'^other2/', include(otherobj2.urls)),
+
+ (r'^ns-included1/', include('regressiontests.urlpatterns_reverse.included_namespace_urls', namespace='inc-ns1')),
+ (r'^ns-included2/', include('regressiontests.urlpatterns_reverse.included_namespace_urls', namespace='inc-ns2')),
+
+ (r'^included/', include('regressiontests.urlpatterns_reverse.included_namespace_urls')),
+
+)
diff --git a/tests/regressiontests/urlpatterns_reverse/tests.py b/tests/regressiontests/urlpatterns_reverse/tests.py
index 9def6b2eb2..d4f281ba81 100644
--- a/tests/regressiontests/urlpatterns_reverse/tests.py
+++ b/tests/regressiontests/urlpatterns_reverse/tests.py
@@ -158,4 +158,84 @@ class ReverseShortcutTests(TestCase):
res = redirect('/foo/')
self.assertEqual(res['Location'], '/foo/')
res = redirect('http://example.com/')
- self.assertEqual(res['Location'], 'http://example.com/') \ No newline at end of file
+ self.assertEqual(res['Location'], 'http://example.com/')
+
+
+class NamespaceTests(TestCase):
+ urls = 'regressiontests.urlpatterns_reverse.namespace_urls'
+
+ def test_ambiguous_object(self):
+ "Names deployed via dynamic URL objects that require namespaces can't be resolved"
+ self.assertRaises(NoReverseMatch, reverse, 'urlobject-view')
+ self.assertRaises(NoReverseMatch, reverse, 'urlobject-view', args=[37,42])
+ self.assertRaises(NoReverseMatch, reverse, 'urlobject-view', kwargs={'arg1':42, 'arg2':37})
+
+ def test_ambiguous_urlpattern(self):
+ "Names deployed via dynamic URL objects that require namespaces can't be resolved"
+ self.assertRaises(NoReverseMatch, reverse, 'inner-nothing')
+ self.assertRaises(NoReverseMatch, reverse, 'inner-nothing', args=[37,42])
+ self.assertRaises(NoReverseMatch, reverse, 'inner-nothing', kwargs={'arg1':42, 'arg2':37})
+
+ def test_non_existent_namespace(self):
+ "Non-existent namespaces raise errors"
+ self.assertRaises(NoReverseMatch, reverse, 'blahblah:urlobject-view')
+ self.assertRaises(NoReverseMatch, reverse, 'test-ns1:blahblah:urlobject-view')
+
+ def test_normal_name(self):
+ "Normal lookups work as expected"
+ self.assertEquals('/normal/', reverse('normal-view'))
+ self.assertEquals('/normal/37/42/', reverse('normal-view', args=[37,42]))
+ self.assertEquals('/normal/42/37/', reverse('normal-view', kwargs={'arg1':42, 'arg2':37}))
+
+ def test_simple_included_name(self):
+ "Normal lookups work on names included from other patterns"
+ self.assertEquals('/included/normal/', reverse('inc-normal-view'))
+ self.assertEquals('/included/normal/37/42/', reverse('inc-normal-view', args=[37,42]))
+ self.assertEquals('/included/normal/42/37/', reverse('inc-normal-view', kwargs={'arg1':42, 'arg2':37}))
+
+ def test_namespace_object(self):
+ "Dynamic URL objects can be found using a namespace"
+ self.assertEquals('/test1/inner/', reverse('test-ns1:urlobject-view'))
+ self.assertEquals('/test1/inner/37/42/', reverse('test-ns1:urlobject-view', args=[37,42]))
+ self.assertEquals('/test1/inner/42/37/', reverse('test-ns1:urlobject-view', kwargs={'arg1':42, 'arg2':37}))
+
+ def test_embedded_namespace_object(self):
+ "Namespaces can be installed anywhere in the URL pattern tree"
+ self.assertEquals('/included/test3/inner/', reverse('test-ns3:urlobject-view'))
+ self.assertEquals('/included/test3/inner/37/42/', reverse('test-ns3:urlobject-view', args=[37,42]))
+ self.assertEquals('/included/test3/inner/42/37/', reverse('test-ns3:urlobject-view', kwargs={'arg1':42, 'arg2':37}))
+
+ def test_namespace_pattern(self):
+ "Namespaces can be applied to include()'d urlpatterns"
+ self.assertEquals('/ns-included1/normal/', reverse('inc-ns1:inc-normal-view'))
+ self.assertEquals('/ns-included1/normal/37/42/', reverse('inc-ns1:inc-normal-view', args=[37,42]))
+ self.assertEquals('/ns-included1/normal/42/37/', reverse('inc-ns1:inc-normal-view', kwargs={'arg1':42, 'arg2':37}))
+
+ def test_multiple_namespace_pattern(self):
+ "Namespaces can be embedded"
+ self.assertEquals('/ns-included1/test3/inner/', reverse('inc-ns1:test-ns3:urlobject-view'))
+ self.assertEquals('/ns-included1/test3/inner/37/42/', reverse('inc-ns1:test-ns3:urlobject-view', args=[37,42]))
+ self.assertEquals('/ns-included1/test3/inner/42/37/', reverse('inc-ns1:test-ns3:urlobject-view', kwargs={'arg1':42, 'arg2':37}))
+
+ def test_app_lookup_object(self):
+ "A default application namespace can be used for lookup"
+ self.assertEquals('/default/inner/', reverse('testapp:urlobject-view'))
+ self.assertEquals('/default/inner/37/42/', reverse('testapp:urlobject-view', args=[37,42]))
+ self.assertEquals('/default/inner/42/37/', reverse('testapp:urlobject-view', kwargs={'arg1':42, 'arg2':37}))
+
+ def test_app_lookup_object_with_default(self):
+ "A default application namespace is sensitive to the 'current' app can be used for lookup"
+ self.assertEquals('/included/test3/inner/', reverse('testapp:urlobject-view', current_app='test-ns3'))
+ self.assertEquals('/included/test3/inner/37/42/', reverse('testapp:urlobject-view', args=[37,42], current_app='test-ns3'))
+ self.assertEquals('/included/test3/inner/42/37/', reverse('testapp:urlobject-view', kwargs={'arg1':42, 'arg2':37}, current_app='test-ns3'))
+
+ def test_app_lookup_object_without_default(self):
+ "An application namespace without a default is sensitive to the 'current' app can be used for lookup"
+ self.assertEquals('/other2/inner/', reverse('nodefault:urlobject-view'))
+ self.assertEquals('/other2/inner/37/42/', reverse('nodefault:urlobject-view', args=[37,42]))
+ self.assertEquals('/other2/inner/42/37/', reverse('nodefault:urlobject-view', kwargs={'arg1':42, 'arg2':37}))
+
+ self.assertEquals('/other1/inner/', reverse('nodefault:urlobject-view', current_app='other-ns1'))
+ self.assertEquals('/other1/inner/37/42/', reverse('nodefault:urlobject-view', args=[37,42], current_app='other-ns1'))
+ self.assertEquals('/other1/inner/42/37/', reverse('nodefault:urlobject-view', kwargs={'arg1':42, 'arg2':37}, current_app='other-ns1'))
+