diff --git a/django/core/urlresolvers.py b/django/core/urlresolvers.py
index 424886e..54d6177 100644
a
|
b
|
class RegexURLResolver(object):
|
303 | 303 | return self._resolve_special('500') |
304 | 304 | |
305 | 305 | def reverse(self, lookup_view, *args, **kwargs): |
| 306 | return self._reverse_with_prefix(lookup_view, '', *args, **kwargs) |
| 307 | |
| 308 | def _reverse_with_prefix(self, lookup_view, _prefix, *args, **kwargs): |
306 | 309 | if args and kwargs: |
307 | 310 | raise ValueError("Don't mix *args and **kwargs in call to reverse()!") |
308 | 311 | try: |
… |
… |
class RegexURLResolver(object):
|
310 | 313 | except (ImportError, AttributeError), e: |
311 | 314 | raise NoReverseMatch("Error importing '%s': %s." % (lookup_view, e)) |
312 | 315 | possibilities = self.reverse_dict.getlist(lookup_view) |
| 316 | prefix_norm, prefix_args = normalize(_prefix)[0] |
313 | 317 | for possibility, pattern, defaults in possibilities: |
314 | 318 | for result, params in possibility: |
315 | 319 | if args: |
316 | | if len(args) != len(params): |
| 320 | if len(args) != len(params) + len(prefix_args): |
317 | 321 | continue |
318 | 322 | unicode_args = [force_unicode(val) for val in args] |
319 | | candidate = result % dict(zip(params, unicode_args)) |
| 323 | candidate = (prefix_norm + result) % dict(zip(params, unicode_args)) |
320 | 324 | else: |
321 | | if set(kwargs.keys() + defaults.keys()) != set(params + defaults.keys()): |
| 325 | if set(kwargs.keys() + defaults.keys()) != set(params + defaults.keys() + prefix_args): |
322 | 326 | continue |
323 | 327 | matches = True |
324 | 328 | for k, v in defaults.items(): |
… |
… |
class RegexURLResolver(object):
|
328 | 332 | if not matches: |
329 | 333 | continue |
330 | 334 | unicode_kwargs = dict([(k, force_unicode(v)) for (k, v) in kwargs.items()]) |
331 | | candidate = result % unicode_kwargs |
332 | | if re.search(u'^%s' % pattern, candidate, re.UNICODE): |
| 335 | candidate = (prefix_norm + result) % unicode_kwargs |
| 336 | if re.search(u'^%s%s' % (_prefix, pattern), candidate, re.UNICODE): |
333 | 337 | return candidate |
334 | 338 | # lookup_view can be URL label, or dotted path, or callable, Any of |
335 | 339 | # 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
|
394 | 398 | else: |
395 | 399 | raise NoReverseMatch("%s is not a registered namespace" % key) |
396 | 400 | |
397 | | return iri_to_uri(u'%s%s' % (prefix, resolver.reverse(view, |
398 | | *args, **kwargs))) |
| 401 | return iri_to_uri(resolver._reverse_with_prefix(view, prefix, *args, **kwargs)) |
399 | 402 | |
400 | 403 | reverse_lazy = lazy(reverse, str) |
401 | 404 | |
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 31a928c..4bdfad8 100644
a
|
b
|
resolve_test_data = (
|
49 | 49 | # Nested namespaces |
50 | 50 | ('/ns-included1/test3/inner/42/37/', 'urlobject-view', 'testapp', 'inc-ns1:test-ns3', 'empty_view', tuple(), {'arg1': '42', 'arg2': '37'}), |
51 | 51 | ('/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'}), |
| 52 | |
| 53 | # Namespaces capturing variables |
| 54 | ('/inc70/', 'inner-nothing', None, 'inc-ns5', views.empty_view, tuple(), {'outer': '70'}), |
| 55 | ('/inc78/extra/foobar/', 'inner-extra', None, 'inc-ns5', views.empty_view, tuple(), {'outer':'78', 'extra':'foobar'}), |
| 56 | |
52 | 57 | ) |
53 | 58 | |
54 | 59 | test_data = ( |