From 738c0de3000c5a1e287f10ddf2f99e0c5e127250 Mon Sep 17 00:00:00 2001 From: Marten Kenbeek Date: Sat, 20 Jun 2015 13:05:35 +0200 Subject: [PATCH] Fixed #14200 -- Added a fallback if HttpRequest.urlconf is None. Made BaseHandler fall back to settings.ROOT_URLCONF if HttpRequest.urlconf is set to None, rather than raising ImproperlyConfigured. --- django/core/handlers/base.py | 4 ++-- docs/ref/request-response.txt | 8 ++++++++ docs/releases/1.9.txt | 4 ++++ docs/topics/http/urls.txt | 6 +++--- tests/urlpatterns_reverse/tests.py | 12 +++++++++++- 5 files changed, 28 insertions(+), 6 deletions(-) diff --git a/django/core/handlers/base.py b/django/core/handlers/base.py index 04c8f79180..b232082fde 100644 --- a/django/core/handlers/base.py +++ b/django/core/handlers/base.py @@ -112,7 +112,7 @@ class BaseHandler(object): # resolver is set urlconf = settings.ROOT_URLCONF urlresolvers.set_urlconf(urlconf) - resolver = urlresolvers.RegexURLResolver(r'^/', urlconf) + resolver = urlresolvers.get_resolver(urlconf) # Use a flag to check if the response was rendered to prevent # multiple renderings or to force rendering if necessary. response_is_rendered = False @@ -129,7 +129,7 @@ class BaseHandler(object): # Reset url resolver with a custom urlconf. urlconf = request.urlconf urlresolvers.set_urlconf(urlconf) - resolver = urlresolvers.RegexURLResolver(r'^/', urlconf) + resolver = urlresolvers.get_resolver(urlconf) resolver_match = resolver.resolve(request.path_info) callback, callback_args, callback_kwargs = resolver_match diff --git a/docs/ref/request-response.txt b/docs/ref/request-response.txt index eba47005a8..6656de5321 100644 --- a/docs/ref/request-response.txt +++ b/docs/ref/request-response.txt @@ -184,6 +184,14 @@ All attributes should be considered read-only, unless stated otherwise below. URLconf for the current request, overriding the :setting:`ROOT_URLCONF` setting. See :ref:`how-django-processes-a-request` for details. + ``urlconf`` can be set to ``None`` to revert any changes made by previous + middleware and return to using the :setting:`ROOT_URLCONF`. + + .. versionchanged:: 1.9 + + Setting ``urlconf=None`` raised + :exc:`~django.core.exceptions.ImproperlyConfigured` in older versions. + .. attribute:: HttpRequest.resolver_match An instance of :class:`~django.core.urlresolvers.ResolverMatch` representing diff --git a/docs/releases/1.9.txt b/docs/releases/1.9.txt index a8c0b960c7..02dba8d2df 100644 --- a/docs/releases/1.9.txt +++ b/docs/releases/1.9.txt @@ -435,6 +435,10 @@ Requests and Responses :class:`~django.template.response.TemplateResponse`, commonly used with class-based views. +* Request middleware can now set :attr:`HttpRequest.urlconf + ` to ``None`` to revert any changes made + by previous middleware and return to using the :setting:`ROOT_URLCONF`. + Tests ^^^^^ diff --git a/docs/topics/http/urls.txt b/docs/topics/http/urls.txt index aec8b74c3d..79b06dae15 100644 --- a/docs/topics/http/urls.txt +++ b/docs/topics/http/urls.txt @@ -40,9 +40,9 @@ algorithm the system follows to determine which Python code to execute: 1. Django determines the root URLconf module to use. Ordinarily, this is the value of the :setting:`ROOT_URLCONF` setting, but if the incoming - ``HttpRequest`` object has an attribute called ``urlconf`` (set by - middleware :ref:`request processing `), its value - will be used in place of the :setting:`ROOT_URLCONF` setting. + ``HttpRequest`` object has a :attr:`~django.http.HttpRequest.urlconf` + attribute (set by middleware :ref:`request processing `), + its value will be used in place of the :setting:`ROOT_URLCONF` setting. 2. Django loads that Python module and looks for the variable ``urlpatterns``. This should be a Python list of :func:`django.conf.urls.url` diff --git a/tests/urlpatterns_reverse/tests.py b/tests/urlpatterns_reverse/tests.py index a8aa0b2e1b..7363084f2a 100644 --- a/tests/urlpatterns_reverse/tests.py +++ b/tests/urlpatterns_reverse/tests.py @@ -700,7 +700,17 @@ class RequestURLconfTests(SimpleTestCase): ] ) def test_urlconf_overridden_with_null(self): - self.assertRaises(ImproperlyConfigured, self.client.get, '/test/me/') + """ + Overriding request.urlconf with None will fall back to the default + URLconf. + """ + response = self.client.get('/test/me/') + self.assertEqual(response.status_code, 200) + self.assertEqual(response.content, b'outer:/test/me/,inner:/inner_urlconf/second_test/') + response = self.client.get('/inner_urlconf/second_test/') + self.assertEqual(response.status_code, 200) + response = self.client.get('/second_test/') + self.assertEqual(response.status_code, 404) @override_settings( MIDDLEWARE_CLASSES=[