mirror of
https://github.com/django/django.git
synced 2025-10-24 06:06:09 +00:00
Fixed #21927 -- Made application and instance namespaces more distinct.
Made URL application namespaces be set in the included URLconf and instance namespaces in the call to include(). Deprecated other ways to set application and instance namespaces.
This commit is contained in:
committed by
Tim Graham
parent
39937de7e6
commit
1e82094f1b
@@ -10,7 +10,7 @@ import unittest
|
||||
from admin_scripts.tests import AdminScriptTestCase
|
||||
|
||||
from django.conf import settings
|
||||
from django.conf.urls import include
|
||||
from django.conf.urls import include, url
|
||||
from django.contrib.auth.models import User
|
||||
from django.core.exceptions import ImproperlyConfigured, ViewDoesNotExist
|
||||
from django.core.urlresolvers import (
|
||||
@@ -26,7 +26,9 @@ from django.test import (
|
||||
)
|
||||
from django.test.utils import override_script_prefix
|
||||
from django.utils import six
|
||||
from django.utils.deprecation import RemovedInDjango20Warning
|
||||
from django.utils.deprecation import (
|
||||
RemovedInDjango20Warning, RemovedInDjango21Warning,
|
||||
)
|
||||
|
||||
from . import middleware, urlconf_outer, views
|
||||
from .views import empty_view
|
||||
@@ -184,6 +186,26 @@ test_data = (
|
||||
)
|
||||
|
||||
|
||||
class URLObject(object):
|
||||
urlpatterns = [
|
||||
url(r'^inner/$', views.empty_view, name='urlobject-view'),
|
||||
url(r'^inner/(?P<arg1>[0-9]+)/(?P<arg2>[0-9]+)/$', views.empty_view, name='urlobject-view'),
|
||||
url(r'^inner/\+\\\$\*/$', views.empty_view, name='urlobject-special-view'),
|
||||
]
|
||||
|
||||
def __init__(self, app_name, namespace=None):
|
||||
self.app_name = app_name
|
||||
self.namespace = namespace
|
||||
|
||||
@property
|
||||
def urls(self):
|
||||
return self.urlpatterns, self.app_name, self.namespace
|
||||
|
||||
@property
|
||||
def app_urls(self):
|
||||
return self.urlpatterns, self.app_name
|
||||
|
||||
|
||||
@override_settings(ROOT_URLCONF='urlpatterns_reverse.no_urls')
|
||||
class NoURLPatternsTests(SimpleTestCase):
|
||||
|
||||
@@ -281,6 +303,7 @@ class URLPatternReverse(SimpleTestCase):
|
||||
|
||||
|
||||
class ResolverTests(unittest.TestCase):
|
||||
@ignore_warnings(category=RemovedInDjango21Warning)
|
||||
def test_resolver_repr(self):
|
||||
"""
|
||||
Test repr of RegexURLResolver, especially when urlconf_name is a list
|
||||
@@ -460,6 +483,7 @@ class ReverseShortcutTests(SimpleTestCase):
|
||||
|
||||
|
||||
@override_settings(ROOT_URLCONF='urlpatterns_reverse.namespace_urls')
|
||||
@ignore_warnings(category=RemovedInDjango21Warning)
|
||||
class NamespaceTests(SimpleTestCase):
|
||||
|
||||
def test_ambiguous_object(self):
|
||||
@@ -500,6 +524,20 @@ class NamespaceTests(SimpleTestCase):
|
||||
self.assertEqual('/test1/inner/42/37/', reverse('test-ns1:urlobject-view', kwargs={'arg1': 42, 'arg2': 37}))
|
||||
self.assertEqual('/test1/inner/+%5C$*/', reverse('test-ns1:urlobject-special-view'))
|
||||
|
||||
def test_app_object(self):
|
||||
"Dynamic URL objects can return a (pattern, app_name) 2-tuple, and include() can set the namespace"
|
||||
self.assertEqual('/newapp1/inner/', reverse('new-ns1:urlobject-view'))
|
||||
self.assertEqual('/newapp1/inner/37/42/', reverse('new-ns1:urlobject-view', args=[37, 42]))
|
||||
self.assertEqual('/newapp1/inner/42/37/', reverse('new-ns1:urlobject-view', kwargs={'arg1': 42, 'arg2': 37}))
|
||||
self.assertEqual('/newapp1/inner/+%5C$*/', reverse('new-ns1:urlobject-special-view'))
|
||||
|
||||
def test_app_object_default_namespace(self):
|
||||
"Namespace defaults to app_name when including a (pattern, app_name) 2-tuple"
|
||||
self.assertEqual('/new-default/inner/', reverse('newapp:urlobject-view'))
|
||||
self.assertEqual('/new-default/inner/37/42/', reverse('newapp:urlobject-view', args=[37, 42]))
|
||||
self.assertEqual('/new-default/inner/42/37/', reverse('newapp:urlobject-view', kwargs={'arg1': 42, 'arg2': 37}))
|
||||
self.assertEqual('/new-default/inner/+%5C$*/', reverse('newapp:urlobject-special-view'))
|
||||
|
||||
def test_embedded_namespace_object(self):
|
||||
"Namespaces can be installed anywhere in the URL pattern tree"
|
||||
self.assertEqual('/included/test3/inner/', reverse('test-ns3:urlobject-view'))
|
||||
@@ -514,6 +552,13 @@ class NamespaceTests(SimpleTestCase):
|
||||
self.assertEqual('/ns-included1/normal/42/37/', reverse('inc-ns1:inc-normal-view', kwargs={'arg1': 42, 'arg2': 37}))
|
||||
self.assertEqual('/ns-included1/+%5C$*/', reverse('inc-ns1:inc-special-view'))
|
||||
|
||||
def test_app_name_pattern(self):
|
||||
"Namespaces can be applied to include()'d urlpatterns that set an app_name attribute"
|
||||
self.assertEqual('/app-included1/normal/', reverse('app-ns1:inc-normal-view'))
|
||||
self.assertEqual('/app-included1/normal/37/42/', reverse('app-ns1:inc-normal-view', args=[37, 42]))
|
||||
self.assertEqual('/app-included1/normal/42/37/', reverse('app-ns1:inc-normal-view', kwargs={'arg1': 42, 'arg2': 37}))
|
||||
self.assertEqual('/app-included1/+%5C$*/', reverse('app-ns1:inc-special-view'))
|
||||
|
||||
def test_namespace_pattern_with_variable_prefix(self):
|
||||
"When using an include with namespaces when there is a regex variable in front of it"
|
||||
self.assertEqual('/ns-outer/42/normal/', reverse('inc-outer:inc-normal-view', kwargs={'outer': 42}))
|
||||
@@ -769,6 +814,7 @@ class NoRootUrlConfTests(SimpleTestCase):
|
||||
@override_settings(ROOT_URLCONF='urlpatterns_reverse.namespace_urls')
|
||||
class ResolverMatchTests(SimpleTestCase):
|
||||
|
||||
@ignore_warnings(category=RemovedInDjango21Warning)
|
||||
def test_urlpattern_resolve(self):
|
||||
for path, url_name, app_name, namespace, view_name, func, args, kwargs in resolve_test_data:
|
||||
# Test legacy support for extracting "function, args, kwargs"
|
||||
@@ -793,6 +839,7 @@ class ResolverMatchTests(SimpleTestCase):
|
||||
self.assertEqual(match[1], args)
|
||||
self.assertEqual(match[2], kwargs)
|
||||
|
||||
@ignore_warnings(category=RemovedInDjango21Warning)
|
||||
def test_resolver_match_on_request(self):
|
||||
response = self.client.get('/resolver_match/')
|
||||
resolver_match = response.resolver_match
|
||||
@@ -845,10 +892,65 @@ class ViewLoadingTests(SimpleTestCase):
|
||||
|
||||
|
||||
class IncludeTests(SimpleTestCase):
|
||||
url_patterns = [
|
||||
url(r'^inner/$', views.empty_view, name='urlobject-view'),
|
||||
url(r'^inner/(?P<arg1>[0-9]+)/(?P<arg2>[0-9]+)/$', views.empty_view, name='urlobject-view'),
|
||||
url(r'^inner/\+\\\$\*/$', views.empty_view, name='urlobject-special-view'),
|
||||
]
|
||||
app_urls = URLObject('inc-app')
|
||||
|
||||
def test_include_app_name_but_no_namespace(self):
|
||||
msg = "Must specify a namespace if specifying app_name."
|
||||
with self.assertRaisesMessage(ValueError, msg):
|
||||
include('urls', app_name='bar')
|
||||
include(self.url_patterns, app_name='bar')
|
||||
|
||||
def test_include_urls(self):
|
||||
self.assertEqual(include(self.url_patterns), (self.url_patterns, None, None))
|
||||
|
||||
@ignore_warnings(category=RemovedInDjango21Warning)
|
||||
def test_include_namespace(self):
|
||||
# no app_name -> deprecated
|
||||
self.assertEqual(include(self.url_patterns, 'namespace'), (self.url_patterns, None, 'namespace'))
|
||||
|
||||
@ignore_warnings(category=RemovedInDjango21Warning)
|
||||
def test_include_namespace_app_name(self):
|
||||
# app_name argument to include -> deprecated
|
||||
self.assertEqual(
|
||||
include(self.url_patterns, 'namespace', 'app_name'),
|
||||
(self.url_patterns, 'app_name', 'namespace')
|
||||
)
|
||||
|
||||
@ignore_warnings(category=RemovedInDjango21Warning)
|
||||
def test_include_3_tuple(self):
|
||||
# 3-tuple -> deprecated
|
||||
self.assertEqual(
|
||||
include((self.url_patterns, 'app_name', 'namespace')),
|
||||
(self.url_patterns, 'app_name', 'namespace')
|
||||
)
|
||||
|
||||
def test_include_2_tuple(self):
|
||||
self.assertEqual(
|
||||
include((self.url_patterns, 'app_name')),
|
||||
(self.url_patterns, 'app_name', 'app_name')
|
||||
)
|
||||
|
||||
def test_include_2_tuple_namespace(self):
|
||||
self.assertEqual(
|
||||
include((self.url_patterns, 'app_name'), namespace='namespace'),
|
||||
(self.url_patterns, 'app_name', 'namespace')
|
||||
)
|
||||
|
||||
def test_include_app_name(self):
|
||||
self.assertEqual(
|
||||
include(self.app_urls),
|
||||
(self.app_urls, 'inc-app', 'inc-app')
|
||||
)
|
||||
|
||||
def test_include_app_name_namespace(self):
|
||||
self.assertEqual(
|
||||
include(self.app_urls, 'namespace'),
|
||||
(self.app_urls, 'inc-app', 'namespace')
|
||||
)
|
||||
|
||||
|
||||
@override_settings(ROOT_URLCONF='urlpatterns_reverse.urls')
|
||||
|
||||
Reference in New Issue
Block a user