Commit 31a789f6 authored by Markus Holtermann's avatar Markus Holtermann Committed by Tim Graham
Browse files

[1.10.x] Fixed #24931 -- Made namespaced RegexURLResolvers populate callback strings.

Fixed a regression in 2f16ff5a.

Thanks Tim Graham for the review.

Backport of 625b8e92 from master
parent 1213ef2b
Loading
Loading
Loading
Loading
+8 −1
Original line number Diff line number Diff line
@@ -164,6 +164,7 @@ class RegexURLResolver(LocaleRegexProvider):
        # urlpatterns
        self._callback_strs = set()
        self._populated = False
        self._populating = False

    def __repr__(self):
        if isinstance(self.urlconf_name, list) and len(self.urlconf_name):
@@ -177,6 +178,9 @@ class RegexURLResolver(LocaleRegexProvider):
        )

    def _populate(self):
        if self._populating:
            return
        self._populating = True
        lookups = MultiValueDict()
        namespaces = {}
        apps = {}
@@ -209,6 +213,8 @@ class RegexURLResolver(LocaleRegexProvider):
                        namespaces[namespace] = (p_pattern + prefix, sub_pattern)
                    for app_name, namespace_list in pattern.app_dict.items():
                        apps.setdefault(app_name, []).extend(namespace_list)
                if not pattern._populating:
                    pattern._populate()
                self._callback_strs.update(pattern._callback_strs)
            else:
                bits = normalize(p_pattern)
@@ -219,6 +225,7 @@ class RegexURLResolver(LocaleRegexProvider):
        self._namespace_dict[language_code] = namespaces
        self._app_dict[language_code] = apps
        self._populated = True
        self._populating = False

    @property
    def reverse_dict(self):
+14 −0
Original line number Diff line number Diff line
from django.conf.urls import include, url
from django.contrib import admin

from . import views

backend_urls = ([
    url(r'^something/$', views.XViewClass.as_view(), name='something'),
], 'backend')

urlpatterns = [
    url(r'^admin/doc/', include('django.contrib.admindocs.urls')),
    url(r'^admin/', admin.site.urls),
    url(r'^api/backend/', include(backend_urls, namespace='backend')),
]
+6 −0
Original line number Diff line number Diff line
@@ -88,6 +88,12 @@ class AdminDocViewTests(TestDataMixin, AdminDocsTestCase):
        # View docstring
        self.assertContains(response, 'Base view for admindocs views.')

    @override_settings(ROOT_URLCONF='admin_docs.namespace_urls')
    def test_namespaced_view_detail(self):
        url = reverse('django-admindocs-views-detail', args=['admin_docs.views.XViewClass'])
        response = self.client.get(url)
        self.assertContains(response, '<h1>admin_docs.views.XViewClass</h1>')

    def test_view_detail_illegal_import(self):
        """
        #23601 - Ensure the view exists in the URLconf.
+25 −0
Original line number Diff line number Diff line
from django.conf.urls import include, url
from django.views import View


def view1(request):
    pass


def view2(request):
    pass


class View3(View):
    pass


nested = ([
    url(r'^view1/$', view1, name='view1'),
    url(r'^view3/$', View3.as_view(), name='view3'),
], 'backend')

urlpatterns = [
    url(r'^some/path/', include(nested, namespace='nested')),
    url(r'^view2/$', view2, name='view2'),
]
+7 −0
Original line number Diff line number Diff line
@@ -428,6 +428,13 @@ class ResolverTests(unittest.TestCase):
                                'Wrong URL name.  Expected "%s", got "%s".' % (e['name'], t.name)
                            )

    def test_namespaced_view_detail(self):
        resolver = get_resolver('urlpatterns_reverse.nested_urls')
        self.assertTrue(resolver._is_callback('urlpatterns_reverse.nested_urls.view1'))
        self.assertTrue(resolver._is_callback('urlpatterns_reverse.nested_urls.view2'))
        self.assertTrue(resolver._is_callback('urlpatterns_reverse.nested_urls.View3'))
        self.assertFalse(resolver._is_callback('urlpatterns_reverse.nested_urls.blub'))


@override_settings(ROOT_URLCONF='urlpatterns_reverse.reverse_lazy_urls')
class ReverseLazyTest(TestCase):