|
18 | 18 |
|
19 | 19 | from django.conf import settings
|
20 | 20 | from django.core.exceptions import ImproperlyConfigured
|
21 |
| -from django.core.urlresolvers import reverse, resolve, NoReverseMatch, Resolver404 |
| 21 | +from django.core.urlresolvers import reverse, resolve, NoReverseMatch, Resolver404, ResolverMatch |
22 | 22 | from django.http import HttpResponseRedirect, HttpResponsePermanentRedirect
|
23 | 23 | from django.shortcuts import redirect
|
24 | 24 | from django.test import TestCase
|
25 | 25 |
|
26 | 26 | import urlconf_outer
|
27 | 27 | import urlconf_inner
|
28 | 28 | import middleware
|
| 29 | +import views |
| 30 | + |
| 31 | +resolve_test_data = ( |
| 32 | + # These entries are in the format: (path, url_name, app_name, namespace, view_func, args, kwargs) |
| 33 | + # Simple case |
| 34 | + ('/normal/42/37/', 'normal-view', None, '', views.empty_view, tuple(), {'arg1': '42', 'arg2': '37'}), |
| 35 | + ('/included/normal/42/37/', 'inc-normal-view', None, '', views.empty_view, tuple(), {'arg1': '42', 'arg2': '37'}), |
| 36 | + |
| 37 | + # Unnamed args are dropped if you have *any* kwargs in a pattern |
| 38 | + ('/mixed_args/42/37/', 'mixed-args', None, '', views.empty_view, tuple(), {'arg2': '37'}), |
| 39 | + ('/included/mixed_args/42/37/', 'inc-mixed-args', None, '', views.empty_view, tuple(), {'arg2': '37'}), |
| 40 | + |
| 41 | + # If you have no kwargs, you get an args list. |
| 42 | + ('/no_kwargs/42/37/', 'no-kwargs', None, '', views.empty_view, ('42','37'), {}), |
| 43 | + ('/included/no_kwargs/42/37/', 'inc-no-kwargs', None, '', views.empty_view, ('42','37'), {}), |
| 44 | + |
| 45 | + # Namespaces |
| 46 | + ('/test1/inner/42/37/', 'urlobject-view', 'testapp', 'test-ns1', 'empty_view', tuple(), {'arg1': '42', 'arg2': '37'}), |
| 47 | + ('/included/test3/inner/42/37/', 'urlobject-view', 'testapp', 'test-ns3', 'empty_view', tuple(), {'arg1': '42', 'arg2': '37'}), |
| 48 | + ('/ns-included1/normal/42/37/', 'inc-normal-view', None, 'inc-ns1', views.empty_view, tuple(), {'arg1': '42', 'arg2': '37'}), |
| 49 | + ('/included/test3/inner/42/37/', 'urlobject-view', 'testapp', 'test-ns3', 'empty_view', tuple(), {'arg1': '42', 'arg2': '37'}), |
| 50 | + ('/default/inner/42/37/', 'urlobject-view', 'testapp', 'testapp', 'empty_view', tuple(), {'arg1': '42', 'arg2': '37'}), |
| 51 | + ('/other2/inner/42/37/', 'urlobject-view', 'nodefault', 'other-ns2', 'empty_view', tuple(), {'arg1': '42', 'arg2': '37'}), |
| 52 | + ('/other1/inner/42/37/', 'urlobject-view', 'nodefault', 'other-ns1', 'empty_view', tuple(), {'arg1': '42', 'arg2': '37'}), |
| 53 | + |
| 54 | + # Nested namespaces |
| 55 | + ('/ns-included1/test3/inner/42/37/', 'urlobject-view', 'testapp', 'inc-ns1:test-ns3', 'empty_view', tuple(), {'arg1': '42', 'arg2': '37'}), |
| 56 | + ('/ns-included1/ns-included4/ns-included2/test3/inner/42/37/', 'urlobject-view', 'testapp', 'inc-ns1:inc-ns4:inc-ns2:test-ns3', 'empty_view', tuple(), {'arg1': '42', 'arg2': '37'}), |
| 57 | +) |
29 | 58 |
|
30 | 59 | test_data = (
|
31 | 60 | ('places', '/places/3/', [3], {}),
|
@@ -229,6 +258,12 @@ def test_multiple_namespace_pattern(self):
|
229 | 258 | self.assertEquals('/ns-included1/test3/inner/37/42/', reverse('inc-ns1:test-ns3:urlobject-view', args=[37,42]))
|
230 | 259 | self.assertEquals('/ns-included1/test3/inner/42/37/', reverse('inc-ns1:test-ns3:urlobject-view', kwargs={'arg1':42, 'arg2':37}))
|
231 | 260 |
|
| 261 | + def test_nested_namespace_pattern(self): |
| 262 | + "Namespaces can be nested" |
| 263 | + self.assertEquals('/ns-included1/ns-included4/ns-included1/test3/inner/', reverse('inc-ns1:inc-ns4:inc-ns1:test-ns3:urlobject-view')) |
| 264 | + self.assertEquals('/ns-included1/ns-included4/ns-included1/test3/inner/37/42/', reverse('inc-ns1:inc-ns4:inc-ns1:test-ns3:urlobject-view', args=[37,42])) |
| 265 | + self.assertEquals('/ns-included1/ns-included4/ns-included1/test3/inner/42/37/', reverse('inc-ns1:inc-ns4:inc-ns1:test-ns3:urlobject-view', kwargs={'arg1':42, 'arg2':37})) |
| 266 | + |
232 | 267 | def test_app_lookup_object(self):
|
233 | 268 | "A default application namespace can be used for lookup"
|
234 | 269 | self.assertEquals('/default/inner/', reverse('testapp:urlobject-view'))
|
@@ -317,3 +352,29 @@ class NoRootUrlConfTests(TestCase):
|
317 | 352 |
|
318 | 353 | def test_no_handler_exception(self):
|
319 | 354 | self.assertRaises(ImproperlyConfigured, self.client.get, '/test/me/')
|
| 355 | + |
| 356 | +class ResolverMatchTests(TestCase): |
| 357 | + urls = 'regressiontests.urlpatterns_reverse.namespace_urls' |
| 358 | + |
| 359 | + def test_urlpattern_resolve(self): |
| 360 | + for path, name, app_name, namespace, func, args, kwargs in resolve_test_data: |
| 361 | + # Test legacy support for extracting "function, args, kwargs" |
| 362 | + match_func, match_args, match_kwargs = resolve(path) |
| 363 | + self.assertEqual(match_func, func) |
| 364 | + self.assertEqual(match_args, args) |
| 365 | + self.assertEqual(match_kwargs, kwargs) |
| 366 | + |
| 367 | + # Test ResolverMatch capabilities. |
| 368 | + match = resolve(path) |
| 369 | + self.assertEqual(match.__class__, ResolverMatch) |
| 370 | + self.assertEqual(match.url_name, name) |
| 371 | + self.assertEqual(match.args, args) |
| 372 | + self.assertEqual(match.kwargs, kwargs) |
| 373 | + self.assertEqual(match.app_name, app_name) |
| 374 | + self.assertEqual(match.namespace, namespace) |
| 375 | + self.assertEqual(match.func, func) |
| 376 | + |
| 377 | + # ... and for legacy purposes: |
| 378 | + self.assertEquals(match[0], func) |
| 379 | + self.assertEquals(match[1], args) |
| 380 | + self.assertEquals(match[2], kwargs) |
0 commit comments