Ticket #17551: #17551-multiple_namespaces.diff

File #17551-multiple_namespaces.diff, 7.4 KB (added by Kronuz, 3 years ago)

Added tests (makes just two of them fail)

  • django/core/urlresolvers.py

    diff --git a/django/core/urlresolvers.py b/django/core/urlresolvers.py
    index b634b56..84cb111 100644
    def get_resolver(urlconf): 
    118118    return RegexURLResolver(r'^/', urlconf)
    119119get_resolver = memoize(get_resolver, _resolver_cache, 1)
    120120
    121 def get_ns_resolver(ns_pattern, resolver):
     121def get_ns_resolver(resolvers):
    122122    # Build a namespaced resolver for the given parent urlconf pattern.
    123123    # This makes it possible to have captured parameters in the parent
    124124    # urlconf pattern.
    125     ns_resolver = RegexURLResolver(ns_pattern,
    126                                           resolver.url_patterns)
    127     return RegexURLResolver(r'^/', [ns_resolver])
     125    ns_resolvers = []
     126    for ns_pattern, resolver in resolvers:
     127        ns_resolvers.append(RegexURLResolver(ns_pattern,
     128                                              resolver.url_patterns))
     129    return RegexURLResolver(r'^/', ns_resolvers)
    128130get_ns_resolver = memoize(get_ns_resolver, _ns_resolver_cache, 2)
    129131
    130132def get_mod_func(callback):
    class RegexURLResolver(LocaleRegexProvider): 
    245247                p_pattern = p_pattern[1:]
    246248            if isinstance(pattern, RegexURLResolver):
    247249                if pattern.namespace:
    248                     namespaces[pattern.namespace] = (p_pattern, pattern)
     250                    namespaces.setdefault(pattern.namespace, []).append((p_pattern, pattern))
    249251                    if pattern.app_name:
    250252                        apps.setdefault(pattern.app_name, []).append(pattern.namespace)
    251253                else:
    class RegexURLResolver(LocaleRegexProvider): 
    256258                            for piece, p_args in parent:
    257259                                new_matches.extend([(piece + suffix, p_args + args) for (suffix, args) in matches])
    258260                            lookups.appendlist(name, (new_matches, p_pattern + pat, dict(defaults, **pattern.default_kwargs)))
    259                     for namespace, (prefix, sub_pattern) in pattern.namespace_dict.items():
    260                         namespaces[namespace] = (p_pattern + prefix, sub_pattern)
     261                    for namespace, resolvers in pattern.namespace_dict.items():
     262                        for prefix, sub_pattern in resolvers:
     263                            namespaces.setdefault(namespace, []).append((p_pattern + prefix, sub_pattern))
    261264                    for app_name, namespace_list in pattern.app_dict.items():
    262265                        apps.setdefault(app_name, []).extend(namespace_list)
    263266            else:
    def reverse(viewname, urlconf=None, args=None, kwargs=None, prefix=None, current 
    437440        view = parts[0]
    438441        path = parts[1:]
    439442
     443        resolvers = []
    440444        resolved_path = []
    441         ns_pattern = ''
     445        ns_patterns = ['']
    442446        while path:
    443447            ns = path.pop()
    444448
    def reverse(viewname, urlconf=None, args=None, kwargs=None, prefix=None, current 
    459463                pass
    460464
    461465            try:
    462                 extra, resolver = resolver.namespace_dict[ns]
     466                _resolvers = resolver.namespace_dict[ns]
    463467                resolved_path.append(ns)
    464                 ns_pattern = ns_pattern + extra
     468                _ns_patterns = []
     469                for extra, resolver in _resolvers:
     470                    for ns_pattern in ns_patterns:
     471                        ns_pattern += extra
     472                        _ns_patterns.append(ns_pattern)
     473                        resolvers.append((ns_pattern, resolver))
    465474            except KeyError, key:
    466475                if resolved_path:
    467476                    raise NoReverseMatch(
    def reverse(viewname, urlconf=None, args=None, kwargs=None, prefix=None, current 
    470479                else:
    471480                    raise NoReverseMatch("%s is not a registered namespace" %
    472481                                         key)
    473         if ns_pattern:
    474             resolver = get_ns_resolver(ns_pattern, resolver)
     482
     483        if resolvers and resolvers[0]:
     484            resolver = get_ns_resolver(tuple(resolvers))
    475485
    476486    return iri_to_uri(resolver._reverse_with_prefix(view, prefix, *args, **kwargs))
    477487
  • tests/regressiontests/urlpatterns_reverse/namespace_urls.py

    diff --git a/tests/regressiontests/urlpatterns_reverse/namespace_urls.py b/tests/regressiontests/urlpatterns_reverse/namespace_urls.py
    index fa892a4..2208d38 100644
    from .views import view_class_instance 
    66
    77
    88class URLObject(object):
    9     def __init__(self, app_name, namespace):
     9    def __init__(self, app_name, namespace, _patterns=None):
     10        if _patterns is None:
     11            _patterns = patterns('',
     12                url(r'^inner/$', 'empty_view', name='urlobject-view'),
     13                url(r'^inner/(?P<arg1>\d+)/(?P<arg2>\d+)/$', 'empty_view', name='urlobject-view'),
     14                url(r'^inner/\+\\\$\*/$', 'empty_view', name='urlobject-special-view'),
     15            )
     16        self.patterns = _patterns
    1017        self.app_name = app_name
    1118        self.namespace = namespace
    1219
    1320    def urls(self):
    14         return patterns('',
    15             url(r'^inner/$', 'empty_view', name='urlobject-view'),
    16             url(r'^inner/(?P<arg1>\d+)/(?P<arg2>\d+)/$', 'empty_view', name='urlobject-view'),
    17             url(r'^inner/\+\\\$\*/$', 'empty_view', name='urlobject-special-view'),
    18         ), self.app_name, self.namespace
     21        return self.patterns, self.app_name, self.namespace
    1922    urls = property(urls)
    2023
    2124testobj1 = URLObject('testapp', 'test-ns1')
    default_testobj = URLObject('testapp', 'testapp') 
    2528otherobj1 = URLObject('nodefault', 'other-ns1')
    2629otherobj2 = URLObject('nodefault', 'other-ns2')
    2730
     31first_patterns = patterns('',
     32    url(r'^$', 'empty_view', name='first'),
     33)
     34first = URLObject('first', 'inc-some', first_patterns)
     35second_patterns = patterns('',
     36    url(r'^$', 'empty_view', name='second'),
     37)
     38second = URLObject('second', 'inc-some', second_patterns)
     39
    2840urlpatterns = patterns('regressiontests.urlpatterns_reverse.views',
    2941    url(r'^normal/$', 'empty_view', name='normal-view'),
    3042    url(r'^normal/(?P<arg1>\d+)/(?P<arg2>\d+)/$', 'empty_view', name='normal-view'),
    urlpatterns = patterns('regressiontests.urlpatterns_reverse.views', 
    5567    (r'^ns-outer/(?P<outer>\d+)/', include('regressiontests.urlpatterns_reverse.included_namespace_urls', namespace='inc-outer')),
    5668
    5769    (r'^\+\\\$\*/', include('regressiontests.urlpatterns_reverse.namespace_urls', namespace='special')),
     70
     71    url(r'^first/', include(first.urls)),
     72    url(r'^second/', include(second.urls)),
    5873)
  • tests/regressiontests/urlpatterns_reverse/tests.py

    diff --git a/tests/regressiontests/urlpatterns_reverse/tests.py b/tests/regressiontests/urlpatterns_reverse/tests.py
    index a1c9244..aef7214 100644
    class NamespaceTests(TestCase): 
    392392        self.assertEqual('/inc70/', reverse('inc-ns5:inner-nothing', args=['70']))
    393393        self.assertEqual('/inc78/extra/foobar/', reverse('inc-ns5:inner-extra', args=['78','foobar']))
    394394
     395    def test_namespaces_in_different_includes(self):
     396        "Namespaces declared in different places: see #17551"
     397        self.assertEqual('/first/', reverse('inc-some:first'))
     398        self.assertEqual('/second/', reverse('inc-some:second'))
     399
    395400class RequestURLconfTests(TestCase):
    396401    def setUp(self):
    397402        self.root_urlconf = settings.ROOT_URLCONF
Back to Top