diff --git a/django/contrib/admindocs/views.py b/django/contrib/admindocs/views.py index bd566cde40..05f42f475b 100644 --- a/django/contrib/admindocs/views.py +++ b/django/contrib/admindocs/views.py @@ -4,7 +4,6 @@ from inspect import cleandoc from pathlib import Path from django.apps import apps -from django.conf import settings from django.contrib import admin from django.contrib.admin.views.decorators import staff_member_required from django.contrib.admindocs import utils @@ -120,8 +119,11 @@ class ViewIndexView(BaseAdminDocsView): def get_context_data(self, **kwargs): views = [] - urlconf = import_module(settings.ROOT_URLCONF) - view_functions = extract_views_from_urlpatterns(urlconf.urlpatterns) + url_resolver = get_resolver(get_urlconf()) + try: + view_functions = extract_views_from_urlpatterns(url_resolver.url_patterns) + except ImproperlyConfigured: + view_functions = [] for (func, regex, namespace, name) in view_functions: views.append({ 'full_name': get_view_name(func), diff --git a/docs/releases/4.0.txt b/docs/releases/4.0.txt index b7b0eec1b2..3d94e8a8a9 100644 --- a/docs/releases/4.0.txt +++ b/docs/releases/4.0.txt @@ -38,7 +38,8 @@ Minor features :mod:`django.contrib.admindocs` ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -* ... +* The admindocs now allows esoteric setups where :setting:`ROOT_URLCONF` is not + a string. :mod:`django.contrib.auth` ~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/tests/admin_docs/test_views.py b/tests/admin_docs/test_views.py index 47bec73a50..266ee98bf8 100644 --- a/tests/admin_docs/test_views.py +++ b/tests/admin_docs/test_views.py @@ -2,6 +2,7 @@ import sys import unittest from django.conf import settings +from django.contrib import admin from django.contrib.admindocs import utils, views from django.contrib.admindocs.views import get_return_data_type, simplify_regex from django.contrib.sites.models import Site @@ -9,7 +10,8 @@ from django.db import models from django.db.models import fields from django.test import SimpleTestCase, modify_settings, override_settings from django.test.utils import captured_stderr -from django.urls import reverse +from django.urls import include, path, reverse +from django.utils.functional import SimpleLazyObject from .models import Company, Person from .tests import AdminDocsTestCase, TestDataMixin @@ -136,6 +138,21 @@ class AdminDocViewTests(TestDataMixin, AdminDocsTestCase): response = self.client.get(reverse('django-admindocs-views-index')) self.assertContains(response, 'View documentation') + def test_callable_urlconf(self): + """ + Index view should correctly resolve view patterns when ROOT_URLCONF is + not a string. + """ + def urlpatterns(): + return ( + path('admin/doc/', include('django.contrib.admindocs.urls')), + path('admin/', admin.site.urls), + ) + + with self.settings(ROOT_URLCONF=SimpleLazyObject(urlpatterns)): + response = self.client.get(reverse('django-admindocs-views-index')) + self.assertEqual(response.status_code, 200) + @override_settings(TEMPLATES=[{ 'NAME': 'ONE',