Skip to content

Commit

Permalink
Fixed django#14200 -- Added a fallback if HttpRequest.urlconf is None.
Browse files Browse the repository at this point in the history
Made BaseHandler fall back to settings.ROOT_URLCONF if
HttpRequest.urlconf is set to None, rather than raising
ImproperlyConfigured.
  • Loading branch information
knbk authored and timgraham committed Jun 20, 2015
1 parent 74402a5 commit 738c0de
Show file tree
Hide file tree
Showing 5 changed files with 28 additions and 6 deletions.
4 changes: 2 additions & 2 deletions django/core/handlers/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ def get_response(self, request):
# 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
Expand All @@ -129,7 +129,7 @@ def get_response(self, request):
# 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
Expand Down
8 changes: 8 additions & 0 deletions docs/ref/request-response.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
4 changes: 4 additions & 0 deletions docs/releases/1.9.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
<django.http.HttpRequest.urlconf>` to ``None`` to revert any changes made
by previous middleware and return to using the :setting:`ROOT_URLCONF`.

Tests
^^^^^

Expand Down
6 changes: 3 additions & 3 deletions docs/topics/http/urls.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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 <request-middleware>`), 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 <request-middleware>`),
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`
Expand Down
12 changes: 11 additions & 1 deletion tests/urlpatterns_reverse/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -700,7 +700,17 @@ def test_urlconf_overridden(self):
]
)
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=[
Expand Down

0 comments on commit 738c0de

Please sign in to comment.