Django

Code

Ticket #5034: set_urlconf.diff

File set_urlconf.diff, 9.3 kB (added by SmileyChris, 6 months ago)
  • django/core/urlresolvers.py

    old new  
    2828# be empty. 
    2929_prefixes = {} 
    3030 
     31# Overridden URLconfs for each thread are stored here. 
     32_urlconfs = {} 
     33 
    3134class Resolver404(Http404): 
    3235    pass 
    3336 
     
    296299        return result + sub_match 
    297300 
    298301def resolve(path, urlconf=None): 
     302    if urlconf is None: 
     303        urlconf = get_urlconf() 
    299304    return get_resolver(urlconf).resolve(path) 
    300305 
    301306def reverse(viewname, urlconf=None, args=None, kwargs=None, prefix=None): 
     307    if urlconf is None: 
     308        urlconf = get_urlconf() 
    302309    args = args or [] 
    303310    kwargs = kwargs or {} 
    304311    if prefix is None: 
     
    328335    """ 
    329336    return _prefixes.get(currentThread(), u'/') 
    330337 
     338def set_urlconf(urlconf_name): 
     339    """ 
     340    Sets the URLconf for the current thread (overriding the default one in 
     341    settings). Set to None to revert back to the default. 
     342    """ 
     343    thread = currentThread() 
     344    if urlconf_name: 
     345        _urlconfs[thread] = urlconf_name 
     346    else: 
     347        # This is a lot faster than wrapping in a try/except. 
     348        if thread in _urlconfs: 
     349            del _urlconfs[thread] 
     350 
     351def get_urlconf(default=None): 
     352    """ 
     353    Returns the root URLconf to use for the current thread if it has been 
     354    changed from the default one. 
     355    """ 
     356    thread = currentThread() 
     357    # It's faster to check first than to do _urlconfs.get(thread) 
     358    if thread in _urlconfs: 
     359        return _urlconfs[thread] 
     360    return default 
  • django/core/handlers/base.py

    old new  
    6363        from django.core import exceptions, urlresolvers 
    6464        from django.conf import settings 
    6565 
     66        # Reset the urlconf for this thread. 
     67        urlresolvers.set_urlconf(None) 
     68 
    6669        # Apply request middleware 
    6770        for middleware_method in self._request_middleware: 
    6871            response = middleware_method(request) 
    6972            if response: 
    7073                return response 
    7174 
    72         # Get urlconf from request object, if available.  Otherwise use default. 
    73         urlconf = getattr(request, "urlconf", settings.ROOT_URLCONF) 
     75        # Get overridden urlconf for this thread, if available. Otherwise use 
     76        # default. 
     77        urlconf = urlresolvers.get_urlconf() 
     78        if urlconf is None: 
     79            # Get urlconf from request object, if available (deprecated). 
     80            if hasattr(request, 'urlconf'): 
     81                import warnings 
     82                warnings.warn("The 'request.urlconf' attribute is deprecated. " 
     83                              "Use the 'django.core.urlresolvers::set_urlconf'" 
     84                              " method instead.", DeprecationWarning) 
     85                urlconf = request.urlconf 
     86                urlresolvers.set_urlconf(urlconf) 
     87            else: 
     88                urlconf = settings.ROOT_URLCONF 
    7489 
    7590        resolver = urlresolvers.RegexURLResolver(r'^/', urlconf) 
    7691        try: 
  • tests/regressiontests/urlpatterns_reverse/middleware.py

    old new  
     1from django.core.urlresolvers import set_urlconf 
     2 
     3import urlconf_inner 
     4 
     5class ChangeUrlconfMiddleware: 
     6    def process_request(self, request): 
     7        set_urlconf(urlconf_inner.__name__) 
  • tests/regressiontests/urlpatterns_reverse/tests.py

    old new  
    11"Unit tests for reverse URL lookup" 
    22 
     3import re 
     4import unittest 
     5 
    36from django.core.urlresolvers import reverse_helper, NoReverseMatch 
    4 import re, unittest 
     7from django.conf import settings 
     8from django.test import TestCase 
    59 
     10import urlconf_outer 
     11import urlconf_inner 
     12import middleware 
     13 
    614test_data = ( 
    715    ('^places/(\d+)/$', 'places/3/', [3], {}), 
    816    ('^places/(\d+)/$', 'places/3/', ['3'], {}), 
     
    3644            else: 
    3745                self.assertEquals(got, expected) 
    3846 
    39 if __name__ == "__main__": 
    40     run_tests(1) 
     47class SetUrlConf(TestCase): 
     48    def setUp(self): 
     49        self.root_urlconf = settings.ROOT_URLCONF 
     50        self.middleware_classes = settings.MIDDLEWARE_CLASSES 
     51        settings.ROOT_URLCONF = urlconf_outer.__name__ 
     52 
     53    def tearDown(self): 
     54        settings.ROOT_URLCONF = self.root_urlconf 
     55        settings.MIDDLEWARE_CLASSES = self.middleware_classes 
     56 
     57    def test_handler(self): 
     58        response = self.client.get('/test/me/') 
     59        self.assertEqual(response.status_code, 200) 
     60        self.assertEqual(response.content, 'outer:/test/me/,' 
     61                                           'inner:/inner_urlconf/second_test/') 
     62        response = self.client.get('/inner_urlconf/second_test/') 
     63        self.assertEqual(response.status_code, 200) 
     64        response = self.client.get('/second_test/') 
     65        self.assertEqual(response.status_code, 404) 
     66 
     67    def test_handler_overridden(self): 
     68        settings.MIDDLEWARE_CLASSES += ( 
     69            '%s.ChangeUrlconfMiddleware' % middleware.__name__, 
     70        ) 
     71        response = self.client.get('/test/me/') 
     72        self.assertEqual(response.status_code, 404) 
     73        response = self.client.get('/inner_urlconf/second_test/') 
     74        self.assertEqual(response.status_code, 404) 
     75        response = self.client.get('/second_test/') 
     76        self.assertEqual(response.status_code, 200) 
     77        self.assertEqual(response.content, 'outer:,inner:/second_test/') 
  • tests/regressiontests/urlpatterns_reverse/urlconf_inner.py

    old new  
     1from django.conf.urls.defaults import * 
     2from django.template import Template, Context 
     3from django.http import HttpResponse 
     4 
     5def inner_view(request): 
     6    content = Template('outer:{% url outer %},' 
     7                       'inner:{% url inner %}').render(Context()) 
     8    return HttpResponse(content) 
     9 
     10urlpatterns = patterns('teacher_survey.views', 
     11    url(r'^second_test/$', inner_view, name='inner'), 
     12) 
     13 
  • tests/regressiontests/urlpatterns_reverse/urlconf_outer.py

    old new  
     1from django.conf.urls.defaults import * 
     2 
     3import urlconf_inner 
     4 
     5urlpatterns = patterns('', 
     6    url(r'^test/me/$', urlconf_inner.inner_view, name='outer'), 
     7    url(r'^inner_urlconf/', include(urlconf_inner.__name__)) 
     8) 
     9 
  • docs/url_dispatch.txt

    old new  
    3434 
    3535    1. Django determines the root URLconf module to use. Ordinarily, 
    3636       this is the value of the ``ROOT_URLCONF`` setting in your 
    37        `settings file`_, but if the incoming ``HttpRequest`` object 
    38        has an attribute called ``urlconf``, its value will be used in 
    39        place of the ``ROOT_URLCONF`` setting
     37       `settings file`_, but this can be overridden per request by calling the 
     38       ``set_urlconf`` method found in ``django.core.urlresolvers`` (passing in 
     39       the value to be used in place of the ``ROOT_URLCONF`` setting)
    4040    2. Django loads that Python module and looks for the variable 
    4141       ``urlpatterns``. This should be a Python list, in the format returned by 
    4242       the function ``django.conf.urls.defaults.patterns()``. 
  • docs/settings.txt

    old new  
    388388 
    389389Still, note that there are always going to be sections of your debug output that 
    390390are inappropriate for public consumption. File paths, configuration options, and 
    391 the like all give attackers extra information about your server.  
     391the like all give attackers extra information about your server. 
    392392 
    393393It is also important to remember that when running with ``DEBUG`` turned on, Django 
    394394will remember every SQL query it executes. This is useful when you are debugging, 
     
    820820 
    821821Default: Not defined 
    822822 
    823 A string representing the full Python import path to your root URLconf. For example: 
    824 ``"mydjangoapps.urls"``. Can be overridden on a per-request basis by 
    825 setting the attribute ``urlconf`` on the incoming ``HttpRequest`` 
    826 object. See `How Django processes a request`_ for details. 
     823A string representing the full Python import path to your root URLconf. For 
     824example: ``"mydjangoapps.urls"``. Can be overridden on a per-request basis by 
     825using the ``set_urlconf`` method in ``django.core.urlresolvers``. See 
     826`How Django processes a request`_ for details. 
    827827 
    828828.. _How Django processes a request: ../url_dispatch/#how-django-processes-a-request 
    829829