Ticket #13922: resolver-match.diff
File resolver-match.diff, 8.6 KB (added by , 14 years ago) |
---|
-
django/core/urlresolvers.py
30 30 # Overridden URLconfs for each thread are stored here. 31 31 _urlconfs = {} 32 32 33 class ResolverMatch(object): 34 def __init__(self, func, args, kwargs, url_name=None, app_name=None, namespaces=[]): 35 self.func = func 36 self.args = args 37 self.kwargs = kwargs 38 self.app_name = app_name 39 self.namespaces = [ x for x in namespaces if x ] 40 if not url_name: 41 url_name = '.'.join([ func.__module__, func.__name__ ]) 42 self.url_name = url_name 43 44 def namespace(self): 45 return ':'.join(self.namespaces) 46 namespace = property(namespace) 47 48 def view_name(self): 49 return ':'.join([ x for x in [ self.namespace, self.url_name ] if x ]) 50 view_name = property(view_name) 51 52 def __getitem__(self, index): 53 return (self.func, self.args, self.kwargs)[index] 54 55 def __repr__(self): 56 return '(%s, %s, %s)' % (self.func, self.args, self.kwargs) 57 58 def reverse(self): 59 return reverse(self.view_name, args=self.args, kwargs=self.kwargs, current_app=self.app_name) 60 33 61 class Resolver404(Http404): 34 62 pass 35 63 … … 120 148 # In both cases, pass any extra_kwargs as **kwargs. 121 149 kwargs.update(self.default_args) 122 150 123 return self.callback, args, kwargs151 return ResolverMatch(self.callback, args, kwargs, self.name) 124 152 125 153 def _get_callback(self): 126 154 if self._callback is not None: … … 224 252 if sub_match: 225 253 sub_match_dict = dict([(smart_str(k), v) for k, v in match.groupdict().items()]) 226 254 sub_match_dict.update(self.default_kwargs) 227 for k, v in sub_match [2].iteritems():255 for k, v in sub_match.kwargs.iteritems(): 228 256 sub_match_dict[smart_str(k)] = v 229 return sub_match[0], sub_match[1], sub_match_dict257 return ResolverMatch(sub_match.func, sub_match.args, sub_match_dict, sub_match.url_name, self.app_name or sub_match.app_name, [ self.namespace ] + sub_match.namespaces) 230 258 tried.append(pattern.regex.pattern) 231 259 raise Resolver404({'tried': tried, 'path': new_path}) 232 260 raise Resolver404({'path' : path}) -
tests/regressiontests/urlpatterns_reverse/tests.py
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 … … 26 26 import urlconf_outer 27 27 import urlconf_inner 28 28 import middleware 29 import views 29 30 31 resolve_test_data = ( 32 # These entries are in the format: (path, url_name, app_name, namespace, view_func, args, kwargs) 33 ('/normal/42/37/', 'normal-view', None, '', views.empty_view, tuple(), {'arg1': '42', 'arg2': '37'}), 34 ('/included/normal/42/37/', 'inc-normal-view', None, '', views.empty_view, tuple(), {'arg1': '42', 'arg2': '37'}), 35 ('/test1/inner/42/37/', 'urlobject-view', 'testapp', 'test-ns1', 'empty_view', tuple(), {'arg1': '42', 'arg2': '37'}), 36 ('/included/test3/inner/42/37/', 'urlobject-view', 'testapp', 'test-ns3', 'empty_view', tuple(), {'arg1': '42', 'arg2': '37'}), 37 ('/ns-included1/normal/42/37/', 'inc-normal-view', None, 'inc-ns1', views.empty_view, tuple(), {'arg1': '42', 'arg2': '37'}), 38 ('/ns-included1/test3/inner/42/37/', 'urlobject-view', 'testapp', 'inc-ns1:test-ns3', 'empty_view', tuple(), {'arg1': '42', 'arg2': '37'}), 39 ('/default/inner/42/37/', 'urlobject-view', 'testapp', 'testapp', 'empty_view', tuple(), {'arg1': '42', 'arg2': '37'}), 40 ('/included/test3/inner/42/37/', 'urlobject-view', 'testapp', 'test-ns3', 'empty_view', tuple(), {'arg1': '42', 'arg2': '37'}), 41 ('/other2/inner/42/37/', 'urlobject-view', 'nodefault', 'other-ns2', 'empty_view', tuple(), {'arg1': '42', 'arg2': '37'}), 42 ('/other1/inner/42/37/', 'urlobject-view', 'nodefault', 'other-ns1', 'empty_view', tuple(), {'arg1': '42', 'arg2': '37'}), 43 ('/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'}), 44 ) 45 30 46 test_data = ( 31 47 ('places', '/places/3/', [3], {}), 32 48 ('places', '/places/3/', ['3'], {}), … … 229 245 self.assertEquals('/ns-included1/test3/inner/37/42/', reverse('inc-ns1:test-ns3:urlobject-view', args=[37,42])) 230 246 self.assertEquals('/ns-included1/test3/inner/42/37/', reverse('inc-ns1:test-ns3:urlobject-view', kwargs={'arg1':42, 'arg2':37})) 231 247 248 def test_nested_namespace_pattern(self): 249 "Namespaces can be nested" 250 self.assertEquals('/ns-included1/ns-included4/ns-included1/test3/inner/', reverse('inc-ns1:inc-ns4:inc-ns1:test-ns3:urlobject-view')) 251 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])) 252 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})) 253 232 254 def test_app_lookup_object(self): 233 255 "A default application namespace can be used for lookup" 234 256 self.assertEquals('/default/inner/', reverse('testapp:urlobject-view')) … … 317 339 318 340 def test_no_handler_exception(self): 319 341 self.assertRaises(ImproperlyConfigured, self.client.get, '/test/me/') 342 343 class ResolverMatchTests(TestCase): 344 urls = 'regressiontests.urlpatterns_reverse.namespace_urls' 345 346 def test_urlpattern_resolve(self): 347 for path, name, app_name, namespace, func, args, kwargs in resolve_test_data: 348 # Test legacy support for extracting "function, args, kwargs" 349 match_func, match_args, match_kwargs = resolve(path) 350 self.assertEqual(match_func, func) 351 self.assertEqual(match_args, args) 352 self.assertEqual(match_kwargs, kwargs) 353 354 # Test ResolverMatch capabilities. 355 match = resolve(path) 356 self.assertEqual(match.__class__, ResolverMatch) 357 self.assertEqual(match.url_name, name) 358 self.assertEqual(match.args, args) 359 self.assertEqual(match.kwargs, kwargs) 360 self.assertEqual(match.app_name, app_name) 361 self.assertEqual(match.namespace, namespace) 362 self.assertEqual(match.func, func) -
tests/regressiontests/urlpatterns_reverse/included_namespace_urls.py
9 9 10 10 (r'^test3/', include(testobj3.urls)), 11 11 (r'^ns-included3/', include('regressiontests.urlpatterns_reverse.included_urls', namespace='inc-ns3')), 12 (r'^ns-included4/', include('regressiontests.urlpatterns_reverse.namespace_urls', namespace='inc-ns4')), 12 13 ) 13 14 -
docs/topics/http/urls.txt
858 858 return HttpResponseRedirect('/') 859 859 return response 860 860 861 .. versionchanged:: 1.3 862 863 The :func:`django.core.urlresolvers.resolve` function returns a 864 :class:`django.core.urlresolvers.ResolverMatch` object that allows you to 865 access various meta-data about the resolved URL including (url_name, app_name, 866 namespace, func, args, kwargs). 867 868 There are two ways to access the results of 869 :func:`django.core.urlresolvers.resolve` in order to maintain backwards 870 compatibility:: 871 872 # Pre-Django 1.3 support for list expansion. 873 func, args, kwargs = resolve('/some/path') 874 875 # ResolverMatch result. 876 match = resolve('/some/path') 877 match.func 878 match.args 879 match.kwargs 880 match.url_name 881 match.app_name 882 match.namespace 883 861 884 permalink() 862 885 ----------- 863 886