Refs #22384 -- Removed the ability to reverse URLs by dotted path per deprecation timeline.
This commit is contained in:
parent
d79122f40b
commit
785cc71d5b
|
@ -79,5 +79,7 @@ def url(regex, view, kwargs=None, name=None):
|
||||||
# For include(...) processing.
|
# For include(...) processing.
|
||||||
urlconf_module, app_name, namespace = view
|
urlconf_module, app_name, namespace = view
|
||||||
return RegexURLResolver(regex, urlconf_module, kwargs, app_name=app_name, namespace=namespace)
|
return RegexURLResolver(regex, urlconf_module, kwargs, app_name=app_name, namespace=namespace)
|
||||||
else:
|
elif callable(view):
|
||||||
return RegexURLPattern(regex, view, kwargs, name)
|
return RegexURLPattern(regex, view, kwargs, name)
|
||||||
|
else:
|
||||||
|
raise TypeError('view must be a callable or a list/tuple in the case of include().')
|
||||||
|
|
|
@ -9,7 +9,6 @@ from __future__ import unicode_literals
|
||||||
|
|
||||||
import functools
|
import functools
|
||||||
import re
|
import re
|
||||||
import warnings
|
|
||||||
from importlib import import_module
|
from importlib import import_module
|
||||||
from threading import local
|
from threading import local
|
||||||
|
|
||||||
|
@ -17,7 +16,6 @@ from django.core.exceptions import ImproperlyConfigured, ViewDoesNotExist
|
||||||
from django.http import Http404
|
from django.http import Http404
|
||||||
from django.utils import lru_cache, six
|
from django.utils import lru_cache, six
|
||||||
from django.utils.datastructures import MultiValueDict
|
from django.utils.datastructures import MultiValueDict
|
||||||
from django.utils.deprecation import RemovedInDjango110Warning
|
|
||||||
from django.utils.encoding import force_str, force_text, iri_to_uri
|
from django.utils.encoding import force_str, force_text, iri_to_uri
|
||||||
from django.utils.functional import cached_property, lazy
|
from django.utils.functional import cached_property, lazy
|
||||||
from django.utils.http import RFC3986_SUBDELIMS, urlquote
|
from django.utils.http import RFC3986_SUBDELIMS, urlquote
|
||||||
|
@ -80,67 +78,50 @@ class NoReverseMatch(Exception):
|
||||||
|
|
||||||
|
|
||||||
@lru_cache.lru_cache(maxsize=None)
|
@lru_cache.lru_cache(maxsize=None)
|
||||||
def get_callable(lookup_view, can_fail=False):
|
def get_callable(lookup_view):
|
||||||
"""
|
"""
|
||||||
Return a callable corresponding to lookup_view. This function is used
|
Return a callable corresponding to lookup_view.
|
||||||
by both resolve() and reverse(), so can_fail allows the caller to choose
|
|
||||||
between returning the input as is and raising an exception when the input
|
|
||||||
string can't be interpreted as an import path.
|
|
||||||
|
|
||||||
If lookup_view is already a callable, return it.
|
* If lookup_view is already a callable, return it.
|
||||||
If lookup_view is a string import path that can be resolved to a callable,
|
* If lookup_view is a string import path that can be resolved to a callable,
|
||||||
import that callable and return it.
|
import that callable and return it, otherwise raise an exception
|
||||||
If lookup_view is some other kind of string and can_fail is True, the string
|
(ImportError or ViewDoesNotExist).
|
||||||
is returned as is. If can_fail is False, an exception is raised (either
|
|
||||||
ImportError or ViewDoesNotExist).
|
|
||||||
"""
|
"""
|
||||||
if callable(lookup_view):
|
if callable(lookup_view):
|
||||||
return lookup_view
|
return lookup_view
|
||||||
|
|
||||||
if not isinstance(lookup_view, six.string_types):
|
if not isinstance(lookup_view, six.string_types):
|
||||||
raise ViewDoesNotExist(
|
raise ViewDoesNotExist("'%s' is not a callable or a dot-notation path" % lookup_view)
|
||||||
"'%s' is not a callable or a dot-notation path" % lookup_view
|
|
||||||
)
|
|
||||||
|
|
||||||
mod_name, func_name = get_mod_func(lookup_view)
|
mod_name, func_name = get_mod_func(lookup_view)
|
||||||
if not func_name: # No '.' in lookup_view
|
if not func_name: # No '.' in lookup_view
|
||||||
if can_fail:
|
raise ImportError("Could not import '%s'. The path must be fully qualified." % lookup_view)
|
||||||
return lookup_view
|
|
||||||
else:
|
|
||||||
raise ImportError(
|
|
||||||
"Could not import '%s'. The path must be fully qualified." %
|
|
||||||
lookup_view)
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
mod = import_module(mod_name)
|
mod = import_module(mod_name)
|
||||||
except ImportError:
|
except ImportError:
|
||||||
if can_fail:
|
parentmod, submod = get_mod_func(mod_name)
|
||||||
return lookup_view
|
if submod and not module_has_submodule(import_module(parentmod), submod):
|
||||||
|
raise ViewDoesNotExist(
|
||||||
|
"Could not import '%s'. Parent module %s does not exist." %
|
||||||
|
(lookup_view, mod_name)
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
parentmod, submod = get_mod_func(mod_name)
|
raise
|
||||||
if submod and not module_has_submodule(import_module(parentmod), submod):
|
|
||||||
raise ViewDoesNotExist(
|
|
||||||
"Could not import '%s'. Parent module %s does not exist." %
|
|
||||||
(lookup_view, mod_name))
|
|
||||||
else:
|
|
||||||
raise
|
|
||||||
else:
|
else:
|
||||||
try:
|
try:
|
||||||
view_func = getattr(mod, func_name)
|
view_func = getattr(mod, func_name)
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
if can_fail:
|
raise ViewDoesNotExist(
|
||||||
return lookup_view
|
"Could not import '%s'. View does not exist in module %s." %
|
||||||
else:
|
(lookup_view, mod_name)
|
||||||
raise ViewDoesNotExist(
|
)
|
||||||
"Could not import '%s'. View does not exist in module %s." %
|
|
||||||
(lookup_view, mod_name))
|
|
||||||
else:
|
else:
|
||||||
if not callable(view_func):
|
if not callable(view_func):
|
||||||
# For backwards compatibility this is raised regardless of can_fail
|
|
||||||
raise ViewDoesNotExist(
|
raise ViewDoesNotExist(
|
||||||
"Could not import '%s.%s'. View is not callable." %
|
"Could not import '%s.%s'. View is not callable." %
|
||||||
(mod_name, func_name))
|
(mod_name, func_name)
|
||||||
|
)
|
||||||
return view_func
|
return view_func
|
||||||
|
|
||||||
|
|
||||||
|
@ -209,14 +190,7 @@ class LocaleRegexProvider(object):
|
||||||
class RegexURLPattern(LocaleRegexProvider):
|
class RegexURLPattern(LocaleRegexProvider):
|
||||||
def __init__(self, regex, callback, default_args=None, name=None):
|
def __init__(self, regex, callback, default_args=None, name=None):
|
||||||
LocaleRegexProvider.__init__(self, regex)
|
LocaleRegexProvider.__init__(self, regex)
|
||||||
# callback is either a string like 'foo.views.news.stories.story_detail'
|
self.callback = callback # the view
|
||||||
# which represents the path to a module and a view function name, or a
|
|
||||||
# callable object (view).
|
|
||||||
if callable(callback):
|
|
||||||
self._callback = callback
|
|
||||||
else:
|
|
||||||
self._callback = None
|
|
||||||
self._callback_str = callback
|
|
||||||
self.default_args = default_args or {}
|
self.default_args = default_args or {}
|
||||||
self.name = name
|
self.name = name
|
||||||
|
|
||||||
|
@ -239,13 +213,19 @@ class RegexURLPattern(LocaleRegexProvider):
|
||||||
|
|
||||||
return ResolverMatch(self.callback, args, kwargs, self.name)
|
return ResolverMatch(self.callback, args, kwargs, self.name)
|
||||||
|
|
||||||
@property
|
@cached_property
|
||||||
def callback(self):
|
def lookup_str(self):
|
||||||
if self._callback is not None:
|
"""
|
||||||
return self._callback
|
A string that identifies the view (e.g. 'path.to.view_function' or
|
||||||
|
'path.to.ClassBasedView').
|
||||||
self._callback = get_callable(self._callback_str)
|
"""
|
||||||
return self._callback
|
callback = self.callback
|
||||||
|
if isinstance(callback, functools.partial):
|
||||||
|
callback = callback.func
|
||||||
|
if not hasattr(callback, '__name__'):
|
||||||
|
return callback.__module__ + "." + callback.__class__.__name__
|
||||||
|
else:
|
||||||
|
return callback.__module__ + "." + callback.__name__
|
||||||
|
|
||||||
|
|
||||||
class RegexURLResolver(LocaleRegexProvider):
|
class RegexURLResolver(LocaleRegexProvider):
|
||||||
|
@ -283,18 +263,8 @@ class RegexURLResolver(LocaleRegexProvider):
|
||||||
apps = {}
|
apps = {}
|
||||||
language_code = get_language()
|
language_code = get_language()
|
||||||
for pattern in reversed(self.url_patterns):
|
for pattern in reversed(self.url_patterns):
|
||||||
if hasattr(pattern, '_callback_str'):
|
if isinstance(pattern, RegexURLPattern):
|
||||||
self._callback_strs.add(pattern._callback_str)
|
self._callback_strs.add(pattern.lookup_str)
|
||||||
elif hasattr(pattern, '_callback'):
|
|
||||||
callback = pattern._callback
|
|
||||||
if isinstance(callback, functools.partial):
|
|
||||||
callback = callback.func
|
|
||||||
|
|
||||||
if not hasattr(callback, '__name__'):
|
|
||||||
lookup_str = callback.__module__ + "." + callback.__class__.__name__
|
|
||||||
else:
|
|
||||||
lookup_str = callback.__module__ + "." + callback.__name__
|
|
||||||
self._callback_strs.add(lookup_str)
|
|
||||||
p_pattern = pattern.regex.pattern
|
p_pattern = pattern.regex.pattern
|
||||||
if p_pattern.startswith('^'):
|
if p_pattern.startswith('^'):
|
||||||
p_pattern = p_pattern[1:]
|
p_pattern = p_pattern[1:]
|
||||||
|
@ -427,9 +397,6 @@ class RegexURLResolver(LocaleRegexProvider):
|
||||||
callback = getattr(urls, 'handler%s' % view_type)
|
callback = getattr(urls, 'handler%s' % view_type)
|
||||||
return get_callable(callback), {}
|
return get_callable(callback), {}
|
||||||
|
|
||||||
def reverse(self, lookup_view, *args, **kwargs):
|
|
||||||
return self._reverse_with_prefix(lookup_view, '', *args, **kwargs)
|
|
||||||
|
|
||||||
def _reverse_with_prefix(self, lookup_view, _prefix, *args, **kwargs):
|
def _reverse_with_prefix(self, lookup_view, _prefix, *args, **kwargs):
|
||||||
if args and kwargs:
|
if args and kwargs:
|
||||||
raise ValueError("Don't mix *args and **kwargs in call to reverse()!")
|
raise ValueError("Don't mix *args and **kwargs in call to reverse()!")
|
||||||
|
@ -439,18 +406,6 @@ class RegexURLResolver(LocaleRegexProvider):
|
||||||
if not self._populated:
|
if not self._populated:
|
||||||
self._populate()
|
self._populate()
|
||||||
|
|
||||||
original_lookup = lookup_view
|
|
||||||
try:
|
|
||||||
if self._is_callback(lookup_view):
|
|
||||||
lookup_view = get_callable(lookup_view, True)
|
|
||||||
except (ImportError, AttributeError) as e:
|
|
||||||
raise NoReverseMatch("Error importing '%s': %s." % (lookup_view, e))
|
|
||||||
else:
|
|
||||||
if not callable(original_lookup) and callable(lookup_view):
|
|
||||||
warnings.warn(
|
|
||||||
'Reversing by dotted path is deprecated (%s).' % original_lookup,
|
|
||||||
RemovedInDjango110Warning, stacklevel=3
|
|
||||||
)
|
|
||||||
possibilities = self.reverse_dict.getlist(lookup_view)
|
possibilities = self.reverse_dict.getlist(lookup_view)
|
||||||
|
|
||||||
for possibility, pattern, defaults in possibilities:
|
for possibility, pattern, defaults in possibilities:
|
||||||
|
@ -484,9 +439,8 @@ class RegexURLResolver(LocaleRegexProvider):
|
||||||
if url.startswith('//'):
|
if url.startswith('//'):
|
||||||
url = '/%%2F%s' % url[2:]
|
url = '/%%2F%s' % url[2:]
|
||||||
return url
|
return url
|
||||||
# lookup_view can be URL label, or dotted path, or callable, Any of
|
# lookup_view can be URL name or callable, but callables are not
|
||||||
# these can be passed in at the top, but callables are not friendly in
|
# friendly in error messages.
|
||||||
# error messages.
|
|
||||||
m = getattr(lookup_view, '__module__', None)
|
m = getattr(lookup_view, '__module__', None)
|
||||||
n = getattr(lookup_view, '__name__', None)
|
n = getattr(lookup_view, '__name__', None)
|
||||||
if m is not None and n is not None:
|
if m is not None and n is not None:
|
||||||
|
|
|
@ -1051,13 +1051,6 @@ This will follow the normal :ref:`namespaced URL resolution strategy
|
||||||
<topics-http-reversing-url-namespaces>`, including using any hints provided
|
<topics-http-reversing-url-namespaces>`, including using any hints provided
|
||||||
by the context as to the current application.
|
by the context as to the current application.
|
||||||
|
|
||||||
.. deprecated:: 1.8
|
|
||||||
|
|
||||||
You can also pass a dotted Python path to a view function, but this syntax
|
|
||||||
is deprecated and will be removed in Django 1.10::
|
|
||||||
|
|
||||||
{% url 'path.to.some_view' v1 v2 %}
|
|
||||||
|
|
||||||
.. warning::
|
.. warning::
|
||||||
|
|
||||||
Don't forget to put quotes around the :func:`~django.conf.urls.url`
|
Don't forget to put quotes around the :func:`~django.conf.urls.url`
|
||||||
|
|
|
@ -12,9 +12,8 @@ your code, Django provides the following function:
|
||||||
|
|
||||||
.. function:: reverse(viewname, urlconf=None, args=None, kwargs=None, current_app=None)
|
.. function:: reverse(viewname, urlconf=None, args=None, kwargs=None, current_app=None)
|
||||||
|
|
||||||
``viewname`` can be a string containing the Python path to the view object, a
|
``viewname`` can be a :ref:`URL pattern name <naming-url-patterns>` or the
|
||||||
:ref:`URL pattern name <naming-url-patterns>`, or the callable view object.
|
callable view object. For example, given the following ``url``::
|
||||||
For example, given the following ``url``::
|
|
||||||
|
|
||||||
from news import views
|
from news import views
|
||||||
|
|
||||||
|
@ -63,24 +62,6 @@ namespaces into URLs on specific application instances, according to the
|
||||||
The ``urlconf`` argument is the URLconf module containing the url patterns to
|
The ``urlconf`` argument is the URLconf module containing the url patterns to
|
||||||
use for reversing. By default, the root URLconf for the current thread is used.
|
use for reversing. By default, the root URLconf for the current thread is used.
|
||||||
|
|
||||||
.. deprecated:: 1.8
|
|
||||||
|
|
||||||
The ability to reverse using the Python path, e.g.
|
|
||||||
``reverse('news.views.archive')``, has been deprecated.
|
|
||||||
|
|
||||||
.. admonition:: Make sure your views are all correct.
|
|
||||||
|
|
||||||
As part of working out which URL names map to which patterns, the
|
|
||||||
``reverse()`` function has to import all of your URLconf files and examine
|
|
||||||
the name of each view. This involves importing each view function. If
|
|
||||||
there are *any* errors whilst importing any of your view functions, it
|
|
||||||
will cause ``reverse()`` to raise an error, even if that view function is
|
|
||||||
not the one you are trying to reverse.
|
|
||||||
|
|
||||||
Make sure that any views you reference in your URLconf files exist and can
|
|
||||||
be imported correctly. Do not include lines that reference views you
|
|
||||||
haven't written yet, because those views will not be importable.
|
|
||||||
|
|
||||||
.. note::
|
.. note::
|
||||||
|
|
||||||
The string returned by ``reverse()`` is already
|
The string returned by ``reverse()`` is already
|
||||||
|
|
|
@ -7,10 +7,8 @@ from xml.dom import minidom
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.contrib.sites.models import Site
|
from django.contrib.sites.models import Site
|
||||||
from django.test import (
|
from django.test import (
|
||||||
TestCase, ignore_warnings, modify_settings, override_settings,
|
TestCase, modify_settings, override_settings, skipUnlessDBFeature,
|
||||||
skipUnlessDBFeature,
|
|
||||||
)
|
)
|
||||||
from django.utils.deprecation import RemovedInDjango110Warning
|
|
||||||
|
|
||||||
from .models import City, Country
|
from .models import City, Country
|
||||||
|
|
||||||
|
@ -30,17 +28,9 @@ class GeoSitemapTest(TestCase):
|
||||||
expected = set(expected)
|
expected = set(expected)
|
||||||
self.assertEqual(actual, expected)
|
self.assertEqual(actual, expected)
|
||||||
|
|
||||||
@ignore_warnings(category=RemovedInDjango110Warning)
|
|
||||||
def test_geositemap_kml(self):
|
def test_geositemap_kml(self):
|
||||||
"Tests KML/KMZ geographic sitemaps."
|
"Tests KML/KMZ geographic sitemaps."
|
||||||
for kml_type in ('kml', 'kmz'):
|
for kml_type in ('kml', 'kmz'):
|
||||||
# The URL for the sitemaps in urls.py have been updated
|
|
||||||
# with a name but since reversing by Python path is tried first
|
|
||||||
# before reversing by name and works since we're giving
|
|
||||||
# name='django.contrib.gis.sitemaps.views.(kml|kmz)', we need
|
|
||||||
# to silence the erroneous warning until reversing by dotted
|
|
||||||
# path is removed. The test will work without modification when
|
|
||||||
# it's removed.
|
|
||||||
doc = minidom.parseString(self.client.get('/sitemaps/%s.xml' % kml_type).content)
|
doc = minidom.parseString(self.client.get('/sitemaps/%s.xml' % kml_type).content)
|
||||||
|
|
||||||
# Ensuring the right sitemaps namespace is present.
|
# Ensuring the right sitemaps namespace is present.
|
||||||
|
|
|
@ -3,9 +3,8 @@ from __future__ import unicode_literals
|
||||||
from django.contrib.auth.views import logout
|
from django.contrib.auth.views import logout
|
||||||
from django.core.urlresolvers import NoReverseMatch, reverse_lazy
|
from django.core.urlresolvers import NoReverseMatch, reverse_lazy
|
||||||
from django.shortcuts import resolve_url
|
from django.shortcuts import resolve_url
|
||||||
from django.test import SimpleTestCase, ignore_warnings, override_settings
|
from django.test import SimpleTestCase, override_settings
|
||||||
from django.utils import six
|
from django.utils import six
|
||||||
from django.utils.deprecation import RemovedInDjango110Warning
|
|
||||||
|
|
||||||
from .models import UnimportantThing
|
from .models import UnimportantThing
|
||||||
|
|
||||||
|
@ -51,8 +50,8 @@ class ResolveUrlTests(SimpleTestCase):
|
||||||
|
|
||||||
def test_view_function(self):
|
def test_view_function(self):
|
||||||
"""
|
"""
|
||||||
Tests that passing a view name to ``resolve_url`` will result in the
|
Tests that passing a view function to ``resolve_url`` will result in
|
||||||
URL path mapping to that view name.
|
the URL path mapping to that view name.
|
||||||
"""
|
"""
|
||||||
resolved_url = resolve_url(logout)
|
resolved_url = resolve_url(logout)
|
||||||
self.assertEqual('/accounts/logout/', resolved_url)
|
self.assertEqual('/accounts/logout/', resolved_url)
|
||||||
|
@ -66,13 +65,12 @@ class ResolveUrlTests(SimpleTestCase):
|
||||||
self.assertIsInstance(resolved_url, six.text_type)
|
self.assertIsInstance(resolved_url, six.text_type)
|
||||||
self.assertEqual('/accounts/logout/', resolved_url)
|
self.assertEqual('/accounts/logout/', resolved_url)
|
||||||
|
|
||||||
@ignore_warnings(category=RemovedInDjango110Warning)
|
|
||||||
def test_valid_view_name(self):
|
def test_valid_view_name(self):
|
||||||
"""
|
"""
|
||||||
Tests that passing a view function to ``resolve_url`` will result in
|
Tests that passing a view name to ``resolve_url`` will result in the
|
||||||
the URL path mapping to that view.
|
URL path mapping to that view.
|
||||||
"""
|
"""
|
||||||
resolved_url = resolve_url('django.contrib.auth.views.logout')
|
resolved_url = resolve_url('logout')
|
||||||
self.assertEqual('/accounts/logout/', resolved_url)
|
self.assertEqual('/accounts/logout/', resolved_url)
|
||||||
|
|
||||||
def test_domain(self):
|
def test_domain(self):
|
||||||
|
|
|
@ -9,9 +9,8 @@ from django.conf import settings
|
||||||
from django.contrib.sitemaps import GenericSitemap, Sitemap
|
from django.contrib.sitemaps import GenericSitemap, Sitemap
|
||||||
from django.contrib.sites.models import Site
|
from django.contrib.sites.models import Site
|
||||||
from django.core.exceptions import ImproperlyConfigured
|
from django.core.exceptions import ImproperlyConfigured
|
||||||
from django.test import ignore_warnings, modify_settings, override_settings
|
from django.test import modify_settings, override_settings
|
||||||
from django.utils._os import upath
|
from django.utils._os import upath
|
||||||
from django.utils.deprecation import RemovedInDjango110Warning
|
|
||||||
from django.utils.formats import localize
|
from django.utils.formats import localize
|
||||||
from django.utils.translation import activate, deactivate
|
from django.utils.translation import activate, deactivate
|
||||||
|
|
||||||
|
@ -21,15 +20,8 @@ from .models import TestModel
|
||||||
|
|
||||||
class HTTPSitemapTests(SitemapTestsBase):
|
class HTTPSitemapTests(SitemapTestsBase):
|
||||||
|
|
||||||
@ignore_warnings(category=RemovedInDjango110Warning)
|
|
||||||
def test_simple_sitemap_index(self):
|
def test_simple_sitemap_index(self):
|
||||||
"A simple sitemap index can be rendered"
|
"A simple sitemap index can be rendered"
|
||||||
# The URL for views.sitemap in tests/urls/http.py has been updated
|
|
||||||
# with a name but since reversing by Python path is tried first
|
|
||||||
# before reversing by name and works since we're giving
|
|
||||||
# name='django.contrib.sitemaps.views.sitemap', we need to silence
|
|
||||||
# the erroneous warning until reversing by dotted path is removed.
|
|
||||||
# The test will work without modification when it's removed.
|
|
||||||
response = self.client.get('/simple/index.xml')
|
response = self.client.get('/simple/index.xml')
|
||||||
expected_content = """<?xml version="1.0" encoding="UTF-8"?>
|
expected_content = """<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<sitemapindex xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
|
<sitemapindex xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
|
||||||
|
@ -38,19 +30,12 @@ class HTTPSitemapTests(SitemapTestsBase):
|
||||||
""" % self.base_url
|
""" % self.base_url
|
||||||
self.assertXMLEqual(response.content.decode('utf-8'), expected_content)
|
self.assertXMLEqual(response.content.decode('utf-8'), expected_content)
|
||||||
|
|
||||||
@ignore_warnings(category=RemovedInDjango110Warning)
|
|
||||||
@override_settings(TEMPLATES=[{
|
@override_settings(TEMPLATES=[{
|
||||||
'BACKEND': 'django.template.backends.django.DjangoTemplates',
|
'BACKEND': 'django.template.backends.django.DjangoTemplates',
|
||||||
'DIRS': [os.path.join(os.path.dirname(upath(__file__)), 'templates')],
|
'DIRS': [os.path.join(os.path.dirname(upath(__file__)), 'templates')],
|
||||||
}])
|
}])
|
||||||
def test_simple_sitemap_custom_index(self):
|
def test_simple_sitemap_custom_index(self):
|
||||||
"A simple sitemap index can be rendered with a custom template"
|
"A simple sitemap index can be rendered with a custom template"
|
||||||
# The URL for views.sitemap in tests/urls/http.py has been updated
|
|
||||||
# with a name but since reversing by Python path is tried first
|
|
||||||
# before reversing by name and works since we're giving
|
|
||||||
# name='django.contrib.sitemaps.views.sitemap', we need to silence
|
|
||||||
# the erroneous warning until reversing by dotted path is removed.
|
|
||||||
# The test will work without modification when it's removed.
|
|
||||||
response = self.client.get('/simple/custom-index.xml')
|
response = self.client.get('/simple/custom-index.xml')
|
||||||
expected_content = """<?xml version="1.0" encoding="UTF-8"?>
|
expected_content = """<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<!-- This is a customised template -->
|
<!-- This is a customised template -->
|
||||||
|
@ -194,14 +179,7 @@ class HTTPSitemapTests(SitemapTestsBase):
|
||||||
""" % self.base_url
|
""" % self.base_url
|
||||||
self.assertXMLEqual(response.content.decode('utf-8'), expected_content)
|
self.assertXMLEqual(response.content.decode('utf-8'), expected_content)
|
||||||
|
|
||||||
@ignore_warnings(category=RemovedInDjango110Warning)
|
|
||||||
def test_x_robots_sitemap(self):
|
def test_x_robots_sitemap(self):
|
||||||
# The URL for views.sitemap in tests/urls/http.py has been updated
|
|
||||||
# with a name but since reversing by Python path is tried first
|
|
||||||
# before reversing by name and works since we're giving
|
|
||||||
# name='django.contrib.sitemaps.views.sitemap', we need to silence
|
|
||||||
# the erroneous warning until reversing by dotted path is removed.
|
|
||||||
# The test will work without modification when it's removed.
|
|
||||||
response = self.client.get('/simple/index.xml')
|
response = self.client.get('/simple/index.xml')
|
||||||
self.assertEqual(response['X-Robots-Tag'], 'noindex, noodp, noarchive')
|
self.assertEqual(response['X-Robots-Tag'], 'noindex, noodp, noarchive')
|
||||||
|
|
||||||
|
|
|
@ -2,8 +2,7 @@ from __future__ import unicode_literals
|
||||||
|
|
||||||
from datetime import date
|
from datetime import date
|
||||||
|
|
||||||
from django.test import ignore_warnings, override_settings
|
from django.test import override_settings
|
||||||
from django.utils.deprecation import RemovedInDjango110Warning
|
|
||||||
|
|
||||||
from .base import SitemapTestsBase
|
from .base import SitemapTestsBase
|
||||||
|
|
||||||
|
@ -12,15 +11,8 @@ from .base import SitemapTestsBase
|
||||||
class HTTPSSitemapTests(SitemapTestsBase):
|
class HTTPSSitemapTests(SitemapTestsBase):
|
||||||
protocol = 'https'
|
protocol = 'https'
|
||||||
|
|
||||||
@ignore_warnings(category=RemovedInDjango110Warning)
|
|
||||||
def test_secure_sitemap_index(self):
|
def test_secure_sitemap_index(self):
|
||||||
"A secure sitemap index can be rendered"
|
"A secure sitemap index can be rendered"
|
||||||
# The URL for views.sitemap in tests/urls/https.py has been updated
|
|
||||||
# with a name but since reversing by Python path is tried first
|
|
||||||
# before reversing by name and works since we're giving
|
|
||||||
# name='django.contrib.sitemaps.views.sitemap', we need to silence
|
|
||||||
# the erroneous warning until reversing by dotted path is removed.
|
|
||||||
# The test will work without modification when it's removed.
|
|
||||||
response = self.client.get('/secure/index.xml')
|
response = self.client.get('/secure/index.xml')
|
||||||
expected_content = """<?xml version="1.0" encoding="UTF-8"?>
|
expected_content = """<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<sitemapindex xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
|
<sitemapindex xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
|
||||||
|
@ -44,15 +36,8 @@ class HTTPSSitemapTests(SitemapTestsBase):
|
||||||
class HTTPSDetectionSitemapTests(SitemapTestsBase):
|
class HTTPSDetectionSitemapTests(SitemapTestsBase):
|
||||||
extra = {'wsgi.url_scheme': 'https'}
|
extra = {'wsgi.url_scheme': 'https'}
|
||||||
|
|
||||||
@ignore_warnings(category=RemovedInDjango110Warning)
|
|
||||||
def test_sitemap_index_with_https_request(self):
|
def test_sitemap_index_with_https_request(self):
|
||||||
"A sitemap index requested in HTTPS is rendered with HTTPS links"
|
"A sitemap index requested in HTTPS is rendered with HTTPS links"
|
||||||
# The URL for views.sitemap in tests/urls/https.py has been updated
|
|
||||||
# with a name but since reversing by Python path is tried first
|
|
||||||
# before reversing by name and works since we're giving
|
|
||||||
# name='django.contrib.sitemaps.views.sitemap', we need to silence
|
|
||||||
# the erroneous warning until reversing by dotted path is removed.
|
|
||||||
# The test will work without modification when it's removed.
|
|
||||||
response = self.client.get('/simple/index.xml', **self.extra)
|
response = self.client.get('/simple/index.xml', **self.extra)
|
||||||
expected_content = """<?xml version="1.0" encoding="UTF-8"?>
|
expected_content = """<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<sitemapindex xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
|
<sitemapindex xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
|
||||||
|
|
|
@ -1,10 +1,7 @@
|
||||||
# coding: utf-8
|
# coding: utf-8
|
||||||
from django.core.urlresolvers import NoReverseMatch, resolve
|
from django.core.urlresolvers import NoReverseMatch, resolve
|
||||||
from django.template import RequestContext, TemplateSyntaxError
|
from django.template import RequestContext, TemplateSyntaxError
|
||||||
from django.test import (
|
from django.test import RequestFactory, SimpleTestCase, override_settings
|
||||||
RequestFactory, SimpleTestCase, ignore_warnings, override_settings,
|
|
||||||
)
|
|
||||||
from django.utils.deprecation import RemovedInDjango110Warning
|
|
||||||
|
|
||||||
from ..utils import setup
|
from ..utils import setup
|
||||||
|
|
||||||
|
@ -13,38 +10,32 @@ from ..utils import setup
|
||||||
class UrlTagTests(SimpleTestCase):
|
class UrlTagTests(SimpleTestCase):
|
||||||
|
|
||||||
# Successes
|
# Successes
|
||||||
@ignore_warnings(category=RemovedInDjango110Warning)
|
@setup({'url01': '{% url "client" client.id %}'})
|
||||||
@setup({'url01': '{% url "template_tests.views.client" client.id %}'})
|
|
||||||
def test_url01(self):
|
def test_url01(self):
|
||||||
output = self.engine.render_to_string('url01', {'client': {'id': 1}})
|
output = self.engine.render_to_string('url01', {'client': {'id': 1}})
|
||||||
self.assertEqual(output, '/client/1/')
|
self.assertEqual(output, '/client/1/')
|
||||||
|
|
||||||
@ignore_warnings(category=RemovedInDjango110Warning)
|
@setup({'url02': '{% url "client_action" id=client.id action="update" %}'})
|
||||||
@setup({'url02': '{% url "template_tests.views.client_action" id=client.id action="update" %}'})
|
|
||||||
def test_url02(self):
|
def test_url02(self):
|
||||||
output = self.engine.render_to_string('url02', {'client': {'id': 1}})
|
output = self.engine.render_to_string('url02', {'client': {'id': 1}})
|
||||||
self.assertEqual(output, '/client/1/update/')
|
self.assertEqual(output, '/client/1/update/')
|
||||||
|
|
||||||
@ignore_warnings(category=RemovedInDjango110Warning)
|
@setup({'url02a': '{% url "client_action" client.id "update" %}'})
|
||||||
@setup({'url02a': '{% url "template_tests.views.client_action" client.id "update" %}'})
|
|
||||||
def test_url02a(self):
|
def test_url02a(self):
|
||||||
output = self.engine.render_to_string('url02a', {'client': {'id': 1}})
|
output = self.engine.render_to_string('url02a', {'client': {'id': 1}})
|
||||||
self.assertEqual(output, '/client/1/update/')
|
self.assertEqual(output, '/client/1/update/')
|
||||||
|
|
||||||
@ignore_warnings(category=RemovedInDjango110Warning)
|
@setup({'url02b': "{% url 'client_action' id=client.id action='update' %}"})
|
||||||
@setup({'url02b': "{% url 'template_tests.views.client_action' id=client.id action='update' %}"})
|
|
||||||
def test_url02b(self):
|
def test_url02b(self):
|
||||||
output = self.engine.render_to_string('url02b', {'client': {'id': 1}})
|
output = self.engine.render_to_string('url02b', {'client': {'id': 1}})
|
||||||
self.assertEqual(output, '/client/1/update/')
|
self.assertEqual(output, '/client/1/update/')
|
||||||
|
|
||||||
@ignore_warnings(category=RemovedInDjango110Warning)
|
@setup({'url02c': "{% url 'client_action' client.id 'update' %}"})
|
||||||
@setup({'url02c': "{% url 'template_tests.views.client_action' client.id 'update' %}"})
|
|
||||||
def test_url02c(self):
|
def test_url02c(self):
|
||||||
output = self.engine.render_to_string('url02c', {'client': {'id': 1}})
|
output = self.engine.render_to_string('url02c', {'client': {'id': 1}})
|
||||||
self.assertEqual(output, '/client/1/update/')
|
self.assertEqual(output, '/client/1/update/')
|
||||||
|
|
||||||
@ignore_warnings(category=RemovedInDjango110Warning)
|
@setup({'url03': '{% url "index" %}'})
|
||||||
@setup({'url03': '{% url "template_tests.views.index" %}'})
|
|
||||||
def test_url03(self):
|
def test_url03(self):
|
||||||
output = self.engine.render_to_string('url03')
|
output = self.engine.render_to_string('url03')
|
||||||
self.assertEqual(output, '/')
|
self.assertEqual(output, '/')
|
||||||
|
@ -64,12 +55,6 @@ class UrlTagTests(SimpleTestCase):
|
||||||
output = self.engine.render_to_string('url06', {'v': 'Ω'})
|
output = self.engine.render_to_string('url06', {'v': 'Ω'})
|
||||||
self.assertEqual(output, '/%D0%AE%D0%BD%D0%B8%D0%BA%D0%BE%D0%B4/%CE%A9/')
|
self.assertEqual(output, '/%D0%AE%D0%BD%D0%B8%D0%BA%D0%BE%D0%B4/%CE%A9/')
|
||||||
|
|
||||||
@ignore_warnings(category=RemovedInDjango110Warning)
|
|
||||||
@setup({'url07': '{% url "template_tests.views.client2" tag=v %}'})
|
|
||||||
def test_url07(self):
|
|
||||||
output = self.engine.render_to_string('url07', {'v': 'Ω'})
|
|
||||||
self.assertEqual(output, '/%D0%AE%D0%BD%D0%B8%D0%BA%D0%BE%D0%B4/%CE%A9/')
|
|
||||||
|
|
||||||
@setup({'url08': '{% url "метка_оператора" v %}'})
|
@setup({'url08': '{% url "метка_оператора" v %}'})
|
||||||
def test_url08(self):
|
def test_url08(self):
|
||||||
output = self.engine.render_to_string('url08', {'v': 'Ω'})
|
output = self.engine.render_to_string('url08', {'v': 'Ω'})
|
||||||
|
@ -80,55 +65,45 @@ class UrlTagTests(SimpleTestCase):
|
||||||
output = self.engine.render_to_string('url09', {'v': 'Ω'})
|
output = self.engine.render_to_string('url09', {'v': 'Ω'})
|
||||||
self.assertEqual(output, '/%D0%AE%D0%BD%D0%B8%D0%BA%D0%BE%D0%B4/%CE%A9/')
|
self.assertEqual(output, '/%D0%AE%D0%BD%D0%B8%D0%BA%D0%BE%D0%B4/%CE%A9/')
|
||||||
|
|
||||||
@ignore_warnings(category=RemovedInDjango110Warning)
|
@setup({'url10': '{% url "client_action" id=client.id action="two words" %}'})
|
||||||
@setup({'url10': '{% url "template_tests.views.client_action" id=client.id action="two words" %}'})
|
|
||||||
def test_url10(self):
|
def test_url10(self):
|
||||||
output = self.engine.render_to_string('url10', {'client': {'id': 1}})
|
output = self.engine.render_to_string('url10', {'client': {'id': 1}})
|
||||||
self.assertEqual(output, '/client/1/two%20words/')
|
self.assertEqual(output, '/client/1/two%20words/')
|
||||||
|
|
||||||
@ignore_warnings(category=RemovedInDjango110Warning)
|
@setup({'url11': '{% url "client_action" id=client.id action="==" %}'})
|
||||||
@setup({'url11': '{% url "template_tests.views.client_action" id=client.id action="==" %}'})
|
|
||||||
def test_url11(self):
|
def test_url11(self):
|
||||||
output = self.engine.render_to_string('url11', {'client': {'id': 1}})
|
output = self.engine.render_to_string('url11', {'client': {'id': 1}})
|
||||||
self.assertEqual(output, '/client/1/==/')
|
self.assertEqual(output, '/client/1/==/')
|
||||||
|
|
||||||
@setup({'url12': '{% url "template_tests.views.client_action" '
|
@setup({'url12': '{% url "client_action" id=client.id action="!$&\'()*+,;=~:@," %}'})
|
||||||
'id=client.id action="!$&\'()*+,;=~:@," %}'})
|
|
||||||
@ignore_warnings(category=RemovedInDjango110Warning)
|
|
||||||
def test_url12(self):
|
def test_url12(self):
|
||||||
output = self.engine.render_to_string('url12', {'client': {'id': 1}})
|
output = self.engine.render_to_string('url12', {'client': {'id': 1}})
|
||||||
self.assertEqual(output, '/client/1/!$&'()*+,;=~:@,/')
|
self.assertEqual(output, '/client/1/!$&'()*+,;=~:@,/')
|
||||||
|
|
||||||
@ignore_warnings(category=RemovedInDjango110Warning)
|
@setup({'url13': '{% url "client_action" id=client.id action=arg|join:"-" %}'})
|
||||||
@setup({'url13': '{% url "template_tests.views.client_action" '
|
|
||||||
'id=client.id action=arg|join:"-" %}'})
|
|
||||||
def test_url13(self):
|
def test_url13(self):
|
||||||
output = self.engine.render_to_string('url13', {'client': {'id': 1}, 'arg': ['a', 'b']})
|
output = self.engine.render_to_string('url13', {'client': {'id': 1}, 'arg': ['a', 'b']})
|
||||||
self.assertEqual(output, '/client/1/a-b/')
|
self.assertEqual(output, '/client/1/a-b/')
|
||||||
|
|
||||||
@ignore_warnings(category=RemovedInDjango110Warning)
|
@setup({'url14': '{% url "client_action" client.id arg|join:"-" %}'})
|
||||||
@setup({'url14': '{% url "template_tests.views.client_action" client.id arg|join:"-" %}'})
|
|
||||||
def test_url14(self):
|
def test_url14(self):
|
||||||
output = self.engine.render_to_string('url14', {'client': {'id': 1}, 'arg': ['a', 'b']})
|
output = self.engine.render_to_string('url14', {'client': {'id': 1}, 'arg': ['a', 'b']})
|
||||||
self.assertEqual(output, '/client/1/a-b/')
|
self.assertEqual(output, '/client/1/a-b/')
|
||||||
|
|
||||||
@ignore_warnings(category=RemovedInDjango110Warning)
|
@setup({'url15': '{% url "client_action" 12 "test" %}'})
|
||||||
@setup({'url15': '{% url "template_tests.views.client_action" 12 "test" %}'})
|
|
||||||
def test_url15(self):
|
def test_url15(self):
|
||||||
output = self.engine.render_to_string('url15')
|
output = self.engine.render_to_string('url15')
|
||||||
self.assertEqual(output, '/client/12/test/')
|
self.assertEqual(output, '/client/12/test/')
|
||||||
|
|
||||||
@ignore_warnings(category=RemovedInDjango110Warning)
|
@setup({'url18': '{% url "client" "1,2" %}'})
|
||||||
@setup({'url18': '{% url "template_tests.views.client" "1,2" %}'})
|
|
||||||
def test_url18(self):
|
def test_url18(self):
|
||||||
output = self.engine.render_to_string('url18')
|
output = self.engine.render_to_string('url18')
|
||||||
self.assertEqual(output, '/client/1,2/')
|
self.assertEqual(output, '/client/1,2/')
|
||||||
|
|
||||||
@ignore_warnings(category=RemovedInDjango110Warning)
|
|
||||||
@setup({'url19': '{% url named_url client.id %}'})
|
@setup({'url19': '{% url named_url client.id %}'})
|
||||||
def test_url19(self):
|
def test_url19(self):
|
||||||
output = self.engine.render_to_string(
|
output = self.engine.render_to_string(
|
||||||
'url19', {'client': {'id': 1}, 'named_url': 'template_tests.views.client'}
|
'url19', {'client': {'id': 1}, 'named_url': 'client'}
|
||||||
)
|
)
|
||||||
self.assertEqual(output, '/client/1/')
|
self.assertEqual(output, '/client/1/')
|
||||||
|
|
||||||
|
@ -138,10 +113,8 @@ class UrlTagTests(SimpleTestCase):
|
||||||
self.assertEqual(output, '/named-client/1/')
|
self.assertEqual(output, '/named-client/1/')
|
||||||
|
|
||||||
@setup({'url21': '{% autoescape off %}'
|
@setup({'url21': '{% autoescape off %}'
|
||||||
'{% url "template_tests.views.client_action" '
|
'{% url "client_action" id=client.id action="!$&\'()*+,;=~:@," %}'
|
||||||
'id=client.id action="!$&\'()*+,;=~:@," %}'
|
|
||||||
'{% endautoescape %}'})
|
'{% endautoescape %}'})
|
||||||
@ignore_warnings(category=RemovedInDjango110Warning)
|
|
||||||
def test_url21(self):
|
def test_url21(self):
|
||||||
output = self.engine.render_to_string('url21', {'client': {'id': 1}})
|
output = self.engine.render_to_string('url21', {'client': {'id': 1}})
|
||||||
self.assertEqual(output, '/client/1/!$&\'()*+,;=~:@,/')
|
self.assertEqual(output, '/client/1/!$&\'()*+,;=~:@,/')
|
||||||
|
@ -157,8 +130,7 @@ class UrlTagTests(SimpleTestCase):
|
||||||
with self.assertRaises(NoReverseMatch):
|
with self.assertRaises(NoReverseMatch):
|
||||||
self.engine.render_to_string('url-fail02')
|
self.engine.render_to_string('url-fail02')
|
||||||
|
|
||||||
@ignore_warnings(category=RemovedInDjango110Warning)
|
@setup({'url-fail03': '{% url "client" %}'})
|
||||||
@setup({'url-fail03': '{% url "template_tests.views.client" %}'})
|
|
||||||
def test_url_fail03(self):
|
def test_url_fail03(self):
|
||||||
with self.assertRaises(NoReverseMatch):
|
with self.assertRaises(NoReverseMatch):
|
||||||
self.engine.render_to_string('url-fail03')
|
self.engine.render_to_string('url-fail03')
|
||||||
|
@ -203,7 +175,6 @@ class UrlTagTests(SimpleTestCase):
|
||||||
with self.assertRaises(NoReverseMatch):
|
with self.assertRaises(NoReverseMatch):
|
||||||
self.engine.render_to_string('url-fail12', {'named_url': 'no_such_view'})
|
self.engine.render_to_string('url-fail12', {'named_url': 'no_such_view'})
|
||||||
|
|
||||||
@ignore_warnings(category=RemovedInDjango110Warning)
|
|
||||||
@setup({'url-fail13': '{% url named_url %}'})
|
@setup({'url-fail13': '{% url named_url %}'})
|
||||||
def test_url_fail13(self):
|
def test_url_fail13(self):
|
||||||
with self.assertRaises(NoReverseMatch):
|
with self.assertRaises(NoReverseMatch):
|
||||||
|
@ -240,14 +211,12 @@ class UrlTagTests(SimpleTestCase):
|
||||||
self.engine.render_to_string('url-fail19', {'named_url': 'view'})
|
self.engine.render_to_string('url-fail19', {'named_url': 'view'})
|
||||||
|
|
||||||
# {% url ... as var %}
|
# {% url ... as var %}
|
||||||
@ignore_warnings(category=RemovedInDjango110Warning)
|
@setup({'url-asvar01': '{% url "index" as url %}'})
|
||||||
@setup({'url-asvar01': '{% url "template_tests.views.index" as url %}'})
|
|
||||||
def test_url_asvar01(self):
|
def test_url_asvar01(self):
|
||||||
output = self.engine.render_to_string('url-asvar01')
|
output = self.engine.render_to_string('url-asvar01')
|
||||||
self.assertEqual(output, '')
|
self.assertEqual(output, '')
|
||||||
|
|
||||||
@ignore_warnings(category=RemovedInDjango110Warning)
|
@setup({'url-asvar02': '{% url "index" as url %}{{ url }}'})
|
||||||
@setup({'url-asvar02': '{% url "template_tests.views.index" as url %}{{ url }}'})
|
|
||||||
def test_url_asvar02(self):
|
def test_url_asvar02(self):
|
||||||
output = self.engine.render_to_string('url-asvar02')
|
output = self.engine.render_to_string('url-asvar02')
|
||||||
self.assertEqual(output, '/')
|
self.assertEqual(output, '/')
|
||||||
|
|
|
@ -7,10 +7,10 @@ from . import views
|
||||||
|
|
||||||
ns_patterns = [
|
ns_patterns = [
|
||||||
# Test urls for testing reverse lookups
|
# Test urls for testing reverse lookups
|
||||||
url(r'^$', views.index),
|
url(r'^$', views.index, name='index'),
|
||||||
url(r'^client/([0-9,]+)/$', views.client),
|
url(r'^client/([0-9,]+)/$', views.client, name='client'),
|
||||||
url(r'^client/(?P<id>[0-9]+)/(?P<action>[^/]+)/$', views.client_action),
|
url(r'^client/(?P<id>[0-9]+)/(?P<action>[^/]+)/$', views.client_action, name='client_action'),
|
||||||
url(r'^client/(?P<client_id>[0-9]+)/(?P<action>[^/]+)/$', views.client_action),
|
url(r'^client/(?P<client_id>[0-9]+)/(?P<action>[^/]+)/$', views.client_action, name='client_action'),
|
||||||
url(r'^named-client/([0-9]+)/$', views.client2, name="named.client"),
|
url(r'^named-client/([0-9]+)/$', views.client2, name="named.client"),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
|
@ -1,30 +1,7 @@
|
||||||
import warnings
|
|
||||||
|
|
||||||
from django.conf.urls import url
|
from django.conf.urls import url
|
||||||
from django.utils.deprecation import RemovedInDjango110Warning
|
|
||||||
|
|
||||||
from . import views
|
from . import views
|
||||||
|
|
||||||
# Test deprecated behavior of passing strings as view to url().
|
urlpatterns = [
|
||||||
# Some of these can be removed in Django 1.10 as they aren't convertable to
|
url(r'(regex_error/$', views.empty_view),
|
||||||
# callables.
|
]
|
||||||
with warnings.catch_warnings():
|
|
||||||
warnings.filterwarnings('ignore', category=RemovedInDjango110Warning)
|
|
||||||
urlpatterns = [
|
|
||||||
# View has erroneous import
|
|
||||||
url(r'erroneous_inner/$', views.erroneous_view),
|
|
||||||
# Module has erroneous import
|
|
||||||
url(r'erroneous_outer/$', 'urlpatterns_reverse.erroneous_views_module.erroneous_view'),
|
|
||||||
# Module is an unqualified string
|
|
||||||
url(r'erroneous_unqualified/$', 'unqualified_view'),
|
|
||||||
# View does not exist
|
|
||||||
url(r'missing_inner/$', 'urlpatterns_reverse.views.missing_view'),
|
|
||||||
# View is not a callable (string import; arbitrary Python object)
|
|
||||||
url(r'uncallable-dotted/$', 'urlpatterns_reverse.views.uncallable'),
|
|
||||||
# View is not a callable (explicit import; arbitrary Python object)
|
|
||||||
url(r'uncallable-object/$', views.uncallable),
|
|
||||||
# Module does not exist
|
|
||||||
url(r'missing_outer/$', 'urlpatterns_reverse.missing_module.missing_view'),
|
|
||||||
# Regex contains an error (refs #6170)
|
|
||||||
url(r'(regex_error/$', views.empty_view),
|
|
||||||
]
|
|
||||||
|
|
|
@ -1,5 +0,0 @@
|
||||||
import non_existent # NOQA
|
|
||||||
|
|
||||||
|
|
||||||
def erroneous_view(request):
|
|
||||||
pass
|
|
|
@ -26,9 +26,7 @@ from django.test import (
|
||||||
)
|
)
|
||||||
from django.test.utils import override_script_prefix
|
from django.test.utils import override_script_prefix
|
||||||
from django.utils import six
|
from django.utils import six
|
||||||
from django.utils.deprecation import (
|
from django.utils.deprecation import RemovedInDjango20Warning
|
||||||
RemovedInDjango20Warning, RemovedInDjango110Warning,
|
|
||||||
)
|
|
||||||
|
|
||||||
from . import middleware, urlconf_outer, views
|
from . import middleware, urlconf_outer, views
|
||||||
from .views import empty_view
|
from .views import empty_view
|
||||||
|
@ -231,13 +229,6 @@ test_data = (
|
||||||
('nested-namedcapture', NoReverseMatch, [], {'outer': 'opt/', 'inner': 'opt'}),
|
('nested-namedcapture', NoReverseMatch, [], {'outer': 'opt/', 'inner': 'opt'}),
|
||||||
('nested-namedcapture', NoReverseMatch, [], {'inner': 'opt'}),
|
('nested-namedcapture', NoReverseMatch, [], {'inner': 'opt'}),
|
||||||
|
|
||||||
# Regression for #9038
|
|
||||||
# These views are resolved by method name. Each method is deployed twice -
|
|
||||||
# once with an explicit argument, and once using the default value on
|
|
||||||
# the method. This is potentially ambiguous, as you have to pick the
|
|
||||||
# correct view for the arguments provided.
|
|
||||||
('urlpatterns_reverse.views.absolute_kwargs_view', '/absolute_arg_view/', [], {}),
|
|
||||||
('urlpatterns_reverse.views.absolute_kwargs_view', '/absolute_arg_view/10/', [], {'arg1': 10}),
|
|
||||||
('non_path_include', '/includes/non_path_include/', [], {}),
|
('non_path_include', '/includes/non_path_include/', [], {}),
|
||||||
|
|
||||||
# Tests for #13154
|
# Tests for #13154
|
||||||
|
@ -292,7 +283,6 @@ class NoURLPatternsTests(SimpleTestCase):
|
||||||
@override_settings(ROOT_URLCONF='urlpatterns_reverse.urls')
|
@override_settings(ROOT_URLCONF='urlpatterns_reverse.urls')
|
||||||
class URLPatternReverse(SimpleTestCase):
|
class URLPatternReverse(SimpleTestCase):
|
||||||
|
|
||||||
@ignore_warnings(category=RemovedInDjango110Warning)
|
|
||||||
def test_urlpattern_reverse(self):
|
def test_urlpattern_reverse(self):
|
||||||
for name, expected, args, kwargs in test_data:
|
for name, expected, args, kwargs in test_data:
|
||||||
try:
|
try:
|
||||||
|
@ -544,11 +534,10 @@ class ReverseShortcutTests(SimpleTestCase):
|
||||||
redirect("urlpatterns_reverse.nonimported_module.view")
|
redirect("urlpatterns_reverse.nonimported_module.view")
|
||||||
self.assertNotIn("urlpatterns_reverse.nonimported_module", sys.modules)
|
self.assertNotIn("urlpatterns_reverse.nonimported_module", sys.modules)
|
||||||
|
|
||||||
@ignore_warnings(category=RemovedInDjango110Warning)
|
|
||||||
def test_reverse_by_path_nested(self):
|
def test_reverse_by_path_nested(self):
|
||||||
# Views that are added to urlpatterns using include() should be
|
# Views added to urlpatterns using include() should be reversible.
|
||||||
# reversible by dotted path.
|
from .views import nested_view
|
||||||
self.assertEqual(reverse('urlpatterns_reverse.views.nested_view'), '/includes/nested_path/')
|
self.assertEqual(reverse(nested_view), '/includes/nested_path/')
|
||||||
|
|
||||||
def test_redirect_view_object(self):
|
def test_redirect_view_object(self):
|
||||||
from .views import absolute_kwargs_view
|
from .views import absolute_kwargs_view
|
||||||
|
@ -982,24 +971,16 @@ class ResolverMatchTests(SimpleTestCase):
|
||||||
@override_settings(ROOT_URLCONF='urlpatterns_reverse.erroneous_urls')
|
@override_settings(ROOT_URLCONF='urlpatterns_reverse.erroneous_urls')
|
||||||
class ErroneousViewTests(SimpleTestCase):
|
class ErroneousViewTests(SimpleTestCase):
|
||||||
|
|
||||||
def test_erroneous_resolve(self):
|
def test_noncallable_view(self):
|
||||||
self.assertRaises(ImportError, self.client.get, '/erroneous_inner/')
|
# View is not a callable (explicit import; arbitrary Python object)
|
||||||
self.assertRaises(ImportError, self.client.get, '/erroneous_outer/')
|
with self.assertRaisesMessage(TypeError, 'view must be a callable'):
|
||||||
self.assertRaises(ViewDoesNotExist, self.client.get, '/missing_inner/')
|
url(r'uncallable-object/$', views.uncallable)
|
||||||
self.assertRaises(ViewDoesNotExist, self.client.get, '/missing_outer/')
|
|
||||||
self.assertRaises(ViewDoesNotExist, self.client.get, '/uncallable-dotted/')
|
|
||||||
self.assertRaises(ViewDoesNotExist, self.client.get, '/uncallable-object/')
|
|
||||||
|
|
||||||
# Regression test for #21157
|
def test_invalid_regex(self):
|
||||||
self.assertRaises(ImportError, self.client.get, '/erroneous_unqualified/')
|
# Regex contains an error (refs #6170)
|
||||||
|
msg = '(regex_error/$" is not a valid regular expression'
|
||||||
def test_erroneous_reverse(self):
|
with self.assertRaisesMessage(ImproperlyConfigured, msg):
|
||||||
"""
|
reverse(views.empty_view)
|
||||||
Ensure that a useful exception is raised when a regex is invalid in the
|
|
||||||
URLConf (#6170).
|
|
||||||
"""
|
|
||||||
# The regex error will be hit before NoReverseMatch can be raised
|
|
||||||
self.assertRaises(ImproperlyConfigured, reverse, 'whatever blah blah')
|
|
||||||
|
|
||||||
|
|
||||||
class ViewLoadingTests(SimpleTestCase):
|
class ViewLoadingTests(SimpleTestCase):
|
||||||
|
|
|
@ -2,7 +2,7 @@ from django.conf.urls import include, url
|
||||||
|
|
||||||
from .views import (
|
from .views import (
|
||||||
absolute_kwargs_view, defaults_view, empty_view, empty_view_partial,
|
absolute_kwargs_view, defaults_view, empty_view, empty_view_partial,
|
||||||
empty_view_wrapped, kwargs_view, nested_view,
|
empty_view_wrapped, nested_view,
|
||||||
)
|
)
|
||||||
|
|
||||||
other_patterns = [
|
other_patterns = [
|
||||||
|
@ -67,10 +67,6 @@ urlpatterns = [
|
||||||
# This is non-reversible, but we shouldn't blow up when parsing it.
|
# This is non-reversible, but we shouldn't blow up when parsing it.
|
||||||
url(r'^(?:foo|bar)(\w+)/$', empty_view, name="disjunction"),
|
url(r'^(?:foo|bar)(\w+)/$', empty_view, name="disjunction"),
|
||||||
|
|
||||||
# Regression views for #9038. See tests for more details
|
|
||||||
url(r'arg_view/$', kwargs_view),
|
|
||||||
url(r'arg_view/(?P<arg1>[0-9]+)/$', kwargs_view),
|
|
||||||
url(r'absolute_arg_view/(?P<arg1>[0-9]+)/$', absolute_kwargs_view),
|
|
||||||
url(r'absolute_arg_view/$', absolute_kwargs_view),
|
url(r'absolute_arg_view/$', absolute_kwargs_view),
|
||||||
|
|
||||||
# Tests for #13154. Mixed syntax to test both ways of defining URLs.
|
# Tests for #13154. Mixed syntax to test both ways of defining URLs.
|
||||||
|
|
|
@ -10,10 +10,6 @@ def empty_view(request, *args, **kwargs):
|
||||||
return HttpResponse('')
|
return HttpResponse('')
|
||||||
|
|
||||||
|
|
||||||
def kwargs_view(request, arg1=1, arg2=2):
|
|
||||||
return HttpResponse('')
|
|
||||||
|
|
||||||
|
|
||||||
def absolute_kwargs_view(request, arg1=1, arg2=2):
|
def absolute_kwargs_view(request, arg1=1, arg2=2):
|
||||||
return HttpResponse('')
|
return HttpResponse('')
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue