diff --git a/django/core/urlresolvers.py b/django/core/urlresolvers.py
index 52d9090..0db5f11 100644
a
|
b
|
class RegexURLResolver(object):
|
302 | 302 | def resolve500(self): |
303 | 303 | return self._resolve_special('500') |
304 | 304 | |
305 | | def reverse(self, lookup_view, *args, **kwargs): |
| 305 | def reverse(self, lookup_view, *args, **kwargs): |
| 306 | prefix = kwargs.pop('__DJANGO_REVERSE_PREFIX','') |
306 | 307 | if args and kwargs: |
307 | 308 | raise ValueError("Don't mix *args and **kwargs in call to reverse()!") |
308 | 309 | try: |
… |
… |
class RegexURLResolver(object):
|
310 | 311 | except (ImportError, AttributeError), e: |
311 | 312 | raise NoReverseMatch("Error importing '%s': %s." % (lookup_view, e)) |
312 | 313 | possibilities = self.reverse_dict.getlist(lookup_view) |
| 314 | prefix_norm, prefix_args = normalize(prefix)[0] |
313 | 315 | for possibility, pattern in possibilities: |
314 | 316 | for result, params in possibility: |
315 | 317 | if args: |
316 | | if len(args) != len(params): |
| 318 | if len(args) != len(params) + len(prefix_args): |
317 | 319 | continue |
318 | 320 | unicode_args = [force_unicode(val) for val in args] |
319 | | candidate = result % dict(zip(params, unicode_args)) |
| 321 | candidate = (prefix_norm + result) % dict(zip(params, unicode_args)) |
320 | 322 | else: |
321 | | if set(kwargs.keys()) != set(params): |
| 323 | if set(kwargs.keys()) != (set(params)|set(prefix_args)): |
322 | 324 | continue |
323 | 325 | unicode_kwargs = dict([(k, force_unicode(v)) for (k, v) in kwargs.items()]) |
324 | | candidate = result % unicode_kwargs |
325 | | if re.search(u'^%s' % pattern, candidate, re.UNICODE): |
| 326 | candidate = (prefix_norm + result) % unicode_kwargs |
| 327 | if re.search(u'^%s%s' % (prefix, pattern), candidate, re.UNICODE): |
326 | 328 | return candidate |
327 | 329 | # lookup_view can be URL label, or dotted path, or callable, Any of |
328 | 330 | # these can be passed in at the top, but callables are not friendly in |
… |
… |
def reverse(viewname, urlconf=None, args=None, kwargs=None, prefix=None, current
|
386 | 388 | raise NoReverseMatch("%s is not a registered namespace inside '%s'" % (key, ':'.join(resolved_path))) |
387 | 389 | else: |
388 | 390 | raise NoReverseMatch("%s is not a registered namespace" % key) |
389 | | |
390 | | return iri_to_uri(u'%s%s' % (prefix, resolver.reverse(view, |
391 | | *args, **kwargs))) |
| 391 | kwargs['__DJANGO_REVERSE_PREFIX'] = prefix |
| 392 | return iri_to_uri(resolver.reverse(view, *args, **kwargs)) |
392 | 393 | |
393 | 394 | reverse_lazy = lazy(reverse, str) |
394 | 395 | |
diff --git a/tests/regressiontests/urlpatterns_reverse/namespace_urls.py b/tests/regressiontests/urlpatterns_reverse/namespace_urls.py
index 3d34049..0544e75 100644
a
|
b
|
urlpatterns = patterns('regressiontests.urlpatterns_reverse.views',
|
37 | 37 | (r'^default/', include(default_testobj.urls)), |
38 | 38 | |
39 | 39 | (r'^other1/', include(otherobj1.urls)), |
40 | | (r'^other2/', include(otherobj2.urls)), |
| 40 | (r'^other[246]/', include(otherobj2.urls)), |
41 | 41 | |
42 | | (r'^ns-included1/', include('regressiontests.urlpatterns_reverse.included_namespace_urls', namespace='inc-ns1')), |
| 42 | (r'^ns-included[135]/', include('regressiontests.urlpatterns_reverse.included_namespace_urls', namespace='inc-ns1')), |
43 | 43 | (r'^ns-included2/', include('regressiontests.urlpatterns_reverse.included_namespace_urls', namespace='inc-ns2')), |
44 | 44 | |
45 | 45 | (r'^included/', include('regressiontests.urlpatterns_reverse.included_namespace_urls')), |
| 46 | (r'^inc(?P<outer>\d+)/', include('regressiontests.urlpatterns_reverse.included_urls', namespace='inc-ns5')), |
46 | 47 | |
47 | 48 | ) |
diff --git a/tests/regressiontests/urlpatterns_reverse/tests.py b/tests/regressiontests/urlpatterns_reverse/tests.py
index 4f391d9..78471ff 100644
a
|
b
|
class NamespaceTests(TestCase):
|
335 | 335 | self.assertEqual('/ns-included1/ns-included4/ns-included1/test3/inner/37/42/', reverse('inc-ns1:inc-ns4:inc-ns1:test-ns3:urlobject-view', args=[37,42])) |
336 | 336 | self.assertEqual('/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})) |
337 | 337 | |
| 338 | def test_nested_namespace_with_variable(self): |
| 339 | self.assertEqual('/inc54/', reverse('inc-ns5:inner-nothing', kwargs={'outer':'54'})) |
| 340 | self.assertEqual('/inc78/extra/foobar/', reverse('inc-ns5:inner-extra', kwargs={'outer':'78', 'extra':'foobar'})) |
| 341 | |
338 | 342 | def test_app_lookup_object(self): |
339 | 343 | "A default application namespace can be used for lookup" |
340 | 344 | self.assertEqual('/default/inner/', reverse('testapp:urlobject-view')) |