Fixed #26013 -- Moved django.core.urlresolvers to django.urls.

Thanks to Tim Graham for the review.
This commit is contained in:
Marten Kenbeek 2015-12-30 16:51:16 +01:00 committed by Tim Graham
parent df3d5b1d73
commit 16411b8400
117 changed files with 961 additions and 922 deletions

View File

@ -15,7 +15,7 @@ def setup(set_prefix=True):
"""
from django.apps import apps
from django.conf import settings
from django.core.urlresolvers import set_script_prefix
from django.urls import set_script_prefix
from django.utils.encoding import force_text
from django.utils.log import configure_logging

View File

@ -2,7 +2,7 @@ import warnings
from importlib import import_module
from django.core.exceptions import ImproperlyConfigured
from django.core.urlresolvers import (
from django.urls import (
LocaleRegexURLResolver, RegexURLPattern, RegexURLResolver,
)
from django.utils import six

View File

@ -1,6 +1,6 @@
from django.conf import settings
from django.conf.urls import url
from django.core.urlresolvers import LocaleRegexURLResolver
from django.urls import LocaleRegexURLResolver
from django.views.i18n import set_language

View File

@ -3,8 +3,8 @@ from __future__ import unicode_literals
from django.conf import settings
from django.contrib.admin.utils import quote
from django.contrib.contenttypes.models import ContentType
from django.core.urlresolvers import NoReverseMatch, reverse
from django.db import models
from django.urls import NoReverseMatch, reverse
from django.utils import timezone
from django.utils.encoding import python_2_unicode_compatible, smart_text
from django.utils.translation import ugettext, ugettext_lazy as _

View File

@ -24,7 +24,6 @@ from django.core.exceptions import (
FieldDoesNotExist, FieldError, PermissionDenied, ValidationError,
)
from django.core.paginator import Paginator
from django.core.urlresolvers import reverse
from django.db import models, router, transaction
from django.db.models.constants import LOOKUP_SEP
from django.db.models.fields import BLANK_CHOICE_DASH
@ -37,6 +36,7 @@ from django.forms.widgets import CheckboxSelectMultiple, SelectMultiple
from django.http import Http404, HttpResponseRedirect
from django.http.response import HttpResponseBase
from django.template.response import SimpleTemplateResponse, TemplateResponse
from django.urls import reverse
from django.utils import six
from django.utils.decorators import method_decorator
from django.utils.encoding import force_text, python_2_unicode_compatible

View File

@ -5,11 +5,11 @@ from django.conf import settings
from django.contrib.admin import ModelAdmin, actions
from django.contrib.auth import REDIRECT_FIELD_NAME
from django.core.exceptions import ImproperlyConfigured, PermissionDenied
from django.core.urlresolvers import NoReverseMatch, reverse
from django.db.models.base import ModelBase
from django.http import Http404, HttpResponseRedirect
from django.template.engine import Engine
from django.template.response import TemplateResponse
from django.urls import NoReverseMatch, reverse
from django.utils import six
from django.utils.text import capfirst
from django.utils.translation import ugettext as _, ugettext_lazy

View File

@ -11,11 +11,11 @@ from django.contrib.admin.views.main import (
ALL_VAR, ORDER_VAR, PAGE_VAR, SEARCH_VAR,
)
from django.core.exceptions import ObjectDoesNotExist
from django.core.urlresolvers import NoReverseMatch
from django.db import models
from django.template import Library
from django.template.loader import get_template
from django.templatetags.static import static
from django.urls import NoReverseMatch
from django.utils import formats
from django.utils.deprecation import RemovedInDjango20Warning
from django.utils.encoding import force_text

View File

@ -1,6 +1,6 @@
from django import template
from django.contrib.admin.utils import quote
from django.core.urlresolvers import Resolver404, get_script_prefix, resolve
from django.urls import Resolver404, get_script_prefix, resolve
from django.utils.http import urlencode
from django.utils.six.moves.urllib.parse import parse_qsl, urlparse, urlunparse

View File

@ -6,12 +6,12 @@ from collections import defaultdict
from django.contrib.auth import get_permission_codename
from django.core.exceptions import FieldDoesNotExist
from django.core.urlresolvers import NoReverseMatch, reverse
from django.db import models
from django.db.models.constants import LOOKUP_SEP
from django.db.models.deletion import Collector
from django.db.models.sql.constants import QUERY_TERMS
from django.forms.utils import pretty_name
from django.urls import NoReverseMatch, reverse
from django.utils import formats, six, timezone
from django.utils.encoding import force_str, force_text, smart_text
from django.utils.html import format_html

View File

@ -15,8 +15,8 @@ from django.core.exceptions import (
FieldDoesNotExist, ImproperlyConfigured, SuspiciousOperation,
)
from django.core.paginator import InvalidPage
from django.core.urlresolvers import reverse
from django.db import models
from django.urls import reverse
from django.utils import six
from django.utils.encoding import force_text
from django.utils.http import urlencode

View File

@ -6,11 +6,11 @@ from __future__ import unicode_literals
import copy
from django import forms
from django.core.urlresolvers import reverse
from django.db.models.deletion import CASCADE
from django.forms.utils import flatatt
from django.forms.widgets import RadioFieldRenderer
from django.template.loader import render_to_string
from django.urls import reverse
from django.utils import six
from django.utils.encoding import force_text
from django.utils.html import (

View File

@ -4,7 +4,7 @@ import re
from email.errors import HeaderParseError
from email.parser import HeaderParser
from django.core.urlresolvers import reverse
from django.urls import reverse
from django.utils.encoding import force_bytes
from django.utils.safestring import mark_safe

View File

@ -8,11 +8,11 @@ from django.conf import settings
from django.contrib import admin
from django.contrib.admin.views.decorators import staff_member_required
from django.contrib.admindocs import utils
from django.core import urlresolvers
from django.core.exceptions import ImproperlyConfigured, ViewDoesNotExist
from django.db import models
from django.http import Http404
from django.template.engine import Engine
from django.urls import get_mod_func, get_resolver, get_urlconf, reverse
from django.utils.decorators import method_decorator
from django.utils.inspect import (
func_accepts_kwargs, func_accepts_var_args, func_has_no_args,
@ -38,7 +38,7 @@ class BaseAdminDocsView(TemplateView):
return super(BaseAdminDocsView, self).dispatch(request, *args, **kwargs)
def get_context_data(self, **kwargs):
kwargs.update({'root_path': urlresolvers.reverse('admin:index')})
kwargs.update({'root_path': reverse('admin:index')})
kwargs.update(admin.site.each_context(self.request))
return super(BaseAdminDocsView, self).get_context_data(**kwargs)
@ -147,9 +147,9 @@ class ViewDetailView(BaseAdminDocsView):
def get_context_data(self, **kwargs):
view = self.kwargs['view']
urlconf = urlresolvers.get_urlconf()
if urlresolvers.get_resolver(urlconf)._is_callback(view):
mod, func = urlresolvers.get_mod_func(view)
urlconf = get_urlconf()
if get_resolver(urlconf)._is_callback(view):
mod, func = get_mod_func(view)
view_func = getattr(import_module(mod), func)
else:
raise Http404

View File

@ -9,10 +9,10 @@ from django.contrib.auth.forms import (
)
from django.contrib.auth.models import Group, User
from django.core.exceptions import PermissionDenied
from django.core.urlresolvers import reverse
from django.db import transaction
from django.http import Http404, HttpResponseRedirect
from django.template.response import TemplateResponse
from django.urls import reverse
from django.utils.decorators import method_decorator
from django.utils.encoding import force_text
from django.utils.html import escape

View File

@ -13,10 +13,10 @@ from django.contrib.auth.forms import (
)
from django.contrib.auth.tokens import default_token_generator
from django.contrib.sites.shortcuts import get_current_site
from django.core.urlresolvers import reverse
from django.http import HttpResponseRedirect, QueryDict
from django.shortcuts import resolve_url
from django.template.response import TemplateResponse
from django.urls import reverse
from django.utils.deprecation import RemovedInDjango20Warning
from django.utils.encoding import force_text
from django.utils.http import is_safe_url, urlsafe_base64_decode

View File

@ -1,8 +1,8 @@
from __future__ import unicode_literals
from django.contrib.sites.models import Site
from django.core.urlresolvers import get_script_prefix
from django.db import models
from django.urls import get_script_prefix
from django.utils.encoding import iri_to_uri, python_2_unicode_compatible
from django.utils.translation import ugettext_lazy as _

View File

@ -1,8 +1,8 @@
from django.apps import apps
from django.contrib.gis.db.models.fields import GeometryField
from django.contrib.sitemaps import Sitemap
from django.core import urlresolvers
from django.db import models
from django.urls import reverse
class KMLSitemap(Sitemap):
@ -56,12 +56,14 @@ class KMLSitemap(Sitemap):
return self.locations
def location(self, obj):
return urlresolvers.reverse('django.contrib.gis.sitemaps.views.%s' % self.geo_format,
kwargs={'label': obj[0],
'model': obj[1],
'field_name': obj[2],
}
)
return reverse(
'django.contrib.gis.sitemaps.views.%s' % self.geo_format,
kwargs={
'label': obj[0],
'model': obj[1],
'field_name': obj[2],
},
)
class KMZSitemap(KMLSitemap):

View File

@ -1,7 +1,8 @@
from django.apps import apps as django_apps
from django.conf import settings
from django.core import paginator, urlresolvers
from django.core import paginator
from django.core.exceptions import ImproperlyConfigured
from django.urls import NoReverseMatch, reverse
from django.utils import translation
from django.utils.six.moves.urllib.parse import urlencode
from django.utils.six.moves.urllib.request import urlopen
@ -18,17 +19,17 @@ def ping_google(sitemap_url=None, ping_url=PING_URL):
Alerts Google that the sitemap for the current site has been updated.
If sitemap_url is provided, it should be an absolute path to the sitemap
for this site -- e.g., '/sitemap.xml'. If sitemap_url is not provided, this
function will attempt to deduce it by using urlresolvers.reverse().
function will attempt to deduce it by using urls.reverse().
"""
if sitemap_url is None:
try:
# First, try to get the "index" sitemap URL.
sitemap_url = urlresolvers.reverse('django.contrib.sitemaps.views.index')
except urlresolvers.NoReverseMatch:
sitemap_url = reverse('django.contrib.sitemaps.views.index')
except NoReverseMatch:
try:
# Next, try for the "global" sitemap URL.
sitemap_url = urlresolvers.reverse('django.contrib.sitemaps.views.sitemap')
except urlresolvers.NoReverseMatch:
sitemap_url = reverse('django.contrib.sitemaps.views.sitemap')
except NoReverseMatch:
pass
if sitemap_url is None:

View File

@ -3,10 +3,10 @@ from calendar import timegm
from functools import wraps
from django.contrib.sites.shortcuts import get_current_site
from django.core import urlresolvers
from django.core.paginator import EmptyPage, PageNotAnInteger
from django.http import Http404
from django.template.response import TemplateResponse
from django.urls import reverse
from django.utils.http import http_date
@ -32,8 +32,7 @@ def index(request, sitemaps,
if callable(site):
site = site()
protocol = req_protocol if site.protocol is None else site.protocol
sitemap_url = urlresolvers.reverse(
sitemap_url_name, kwargs={'section': section})
sitemap_url = reverse(sitemap_url_name, kwargs={'section': section})
absolute_url = '%s://%s%s' % (protocol, req_site.domain, sitemap_url)
sites.append(absolute_url)
for page in range(2, site.paginator.num_pages + 1):

View File

@ -5,7 +5,7 @@ from . import Tags, Warning, register
@register(Tags.urls)
def check_url_config(app_configs, **kwargs):
from django.core.urlresolvers import get_resolver
from django.urls import get_resolver
resolver = get_resolver()
return check_resolver(resolver)
@ -14,7 +14,7 @@ def check_resolver(resolver):
"""
Recursively check the resolver.
"""
from django.core.urlresolvers import RegexURLPattern, RegexURLResolver
from django.urls import RegexURLPattern, RegexURLResolver
warnings = []
for pattern in resolver.url_patterns:
if isinstance(pattern, RegexURLResolver):

View File

@ -7,12 +7,13 @@ import warnings
from django import http
from django.conf import settings
from django.core import signals, urlresolvers
from django.core import signals
from django.core.exceptions import (
MiddlewareNotUsed, PermissionDenied, SuspiciousOperation,
)
from django.db import connections, transaction
from django.http.multipartparser import MultiPartParserError
from django.urls import get_resolver, set_urlconf
from django.utils import six
from django.utils.deprecation import RemovedInDjango20Warning
from django.utils.encoding import force_text
@ -111,8 +112,8 @@ class BaseHandler(object):
# variable" exception in the event an exception is raised before
# resolver is set
urlconf = settings.ROOT_URLCONF
urlresolvers.set_urlconf(urlconf)
resolver = urlresolvers.get_resolver(urlconf)
set_urlconf(urlconf)
resolver = 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
@ -128,8 +129,8 @@ class BaseHandler(object):
if hasattr(request, 'urlconf'):
# Reset url resolver with a custom URLconf.
urlconf = request.urlconf
urlresolvers.set_urlconf(urlconf)
resolver = urlresolvers.get_resolver(urlconf)
set_urlconf(urlconf)
resolver = get_resolver(urlconf)
resolver_match = resolver.resolve(request.path_info)
callback, callback_args, callback_kwargs = resolver_match

View File

@ -12,7 +12,7 @@ from django import http
from django.conf import settings
from django.core import signals
from django.core.handlers import base
from django.core.urlresolvers import set_script_prefix
from django.urls import set_script_prefix
from django.utils import six
from django.utils.encoding import force_str, force_text
from django.utils.functional import cached_property

View File

@ -1,640 +1,9 @@
"""
This module converts requested URLs to callback view functions.
import warnings
RegexURLResolver is the main class here. Its resolve() method takes a URL (as
a string) and returns a ResolverMatch object which provides access to all
attributes of the resolved URL match.
"""
from __future__ import unicode_literals
from django.urls import * # NOQA
from django.utils.deprecation import RemovedInDjango20Warning
import functools
import re
from importlib import import_module
from threading import local
from django.core.exceptions import ImproperlyConfigured, ViewDoesNotExist
from django.http import Http404
from django.utils import lru_cache, six
from django.utils.datastructures import MultiValueDict
from django.utils.encoding import force_str, force_text, iri_to_uri
from django.utils.functional import cached_property, lazy
from django.utils.http import RFC3986_SUBDELIMS, urlquote
from django.utils.module_loading import module_has_submodule
from django.utils.regex_helper import normalize
from django.utils.six.moves.urllib.parse import urlsplit, urlunsplit
from django.utils.translation import get_language, override
# SCRIPT_NAME prefixes for each thread are stored here. If there's no entry for
# the current thread (which is the only one we ever access), it is assumed to
# be empty.
_prefixes = local()
# Overridden URLconfs for each thread are stored here.
_urlconfs = local()
class ResolverMatch(object):
def __init__(self, func, args, kwargs, url_name=None, app_names=None, namespaces=None):
self.func = func
self.args = args
self.kwargs = kwargs
self.url_name = url_name
# If a URLRegexResolver doesn't have a namespace or app_name, it passes
# in an empty value.
self.app_names = [x for x in app_names if x] if app_names else []
self.app_name = ':'.join(self.app_names)
if namespaces:
self.namespaces = [x for x in namespaces if x]
else:
self.namespaces = []
self.namespace = ':'.join(self.namespaces)
if not hasattr(func, '__name__'):
# A class-based view
self._func_path = '.'.join([func.__class__.__module__, func.__class__.__name__])
else:
# A function-based view
self._func_path = '.'.join([func.__module__, func.__name__])
view_path = url_name or self._func_path
self.view_name = ':'.join(self.namespaces + [view_path])
def __getitem__(self, index):
return (self.func, self.args, self.kwargs)[index]
def __repr__(self):
return "ResolverMatch(func=%s, args=%s, kwargs=%s, url_name=%s, app_names=%s, namespaces=%s)" % (
self._func_path, self.args, self.kwargs, self.url_name, self.app_names, self.namespaces)
class Resolver404(Http404):
pass
class NoReverseMatch(Exception):
pass
@lru_cache.lru_cache(maxsize=None)
def get_callable(lookup_view):
"""
Return a callable corresponding to lookup_view.
* If lookup_view is already a callable, return it.
* If lookup_view is a string import path that can be resolved to a callable,
import that callable and return it, otherwise raise an exception
(ImportError or ViewDoesNotExist).
"""
if callable(lookup_view):
return lookup_view
if not isinstance(lookup_view, six.string_types):
raise ViewDoesNotExist("'%s' is not a callable or a dot-notation path" % lookup_view)
mod_name, func_name = get_mod_func(lookup_view)
if not func_name: # No '.' in lookup_view
raise ImportError("Could not import '%s'. The path must be fully qualified." % lookup_view)
try:
mod = import_module(mod_name)
except ImportError:
parentmod, submod = get_mod_func(mod_name)
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:
try:
view_func = getattr(mod, func_name)
except AttributeError:
raise ViewDoesNotExist(
"Could not import '%s'. View does not exist in module %s." %
(lookup_view, mod_name)
)
else:
if not callable(view_func):
raise ViewDoesNotExist(
"Could not import '%s.%s'. View is not callable." %
(mod_name, func_name)
)
return view_func
@lru_cache.lru_cache(maxsize=None)
def get_resolver(urlconf=None):
if urlconf is None:
from django.conf import settings
urlconf = settings.ROOT_URLCONF
return RegexURLResolver(r'^/', urlconf)
@lru_cache.lru_cache(maxsize=None)
def get_ns_resolver(ns_pattern, resolver):
# Build a namespaced resolver for the given parent URLconf pattern.
# This makes it possible to have captured parameters in the parent
# URLconf pattern.
ns_resolver = RegexURLResolver(ns_pattern, resolver.url_patterns)
return RegexURLResolver(r'^/', [ns_resolver])
def get_mod_func(callback):
# Converts 'django.views.news.stories.story_detail' to
# ['django.views.news.stories', 'story_detail']
try:
dot = callback.rindex('.')
except ValueError:
return callback, ''
return callback[:dot], callback[dot + 1:]
class LocaleRegexProvider(object):
"""
A mixin to provide a default regex property which can vary by active
language.
"""
def __init__(self, regex):
# regex is either a string representing a regular expression, or a
# translatable string (using ugettext_lazy) representing a regular
# expression.
self._regex = regex
self._regex_dict = {}
@property
def regex(self):
"""
Returns a compiled regular expression, depending upon the activated
language-code.
"""
language_code = get_language()
if language_code not in self._regex_dict:
if isinstance(self._regex, six.string_types):
regex = self._regex
else:
regex = force_text(self._regex)
try:
compiled_regex = re.compile(regex, re.UNICODE)
except re.error as e:
raise ImproperlyConfigured(
'"%s" is not a valid regular expression: %s' %
(regex, six.text_type(e)))
self._regex_dict[language_code] = compiled_regex
return self._regex_dict[language_code]
class RegexURLPattern(LocaleRegexProvider):
def __init__(self, regex, callback, default_args=None, name=None):
LocaleRegexProvider.__init__(self, regex)
self.callback = callback # the view
self.default_args = default_args or {}
self.name = name
def __repr__(self):
return force_str('<%s %s %s>' % (self.__class__.__name__, self.name, self.regex.pattern))
def resolve(self, path):
match = self.regex.search(path)
if match:
# If there are any named groups, use those as kwargs, ignoring
# non-named groups. Otherwise, pass all non-named arguments as
# positional arguments.
kwargs = match.groupdict()
if kwargs:
args = ()
else:
args = match.groups()
# In both cases, pass any extra_kwargs as **kwargs.
kwargs.update(self.default_args)
return ResolverMatch(self.callback, args, kwargs, self.name)
@cached_property
def lookup_str(self):
"""
A string that identifies the view (e.g. 'path.to.view_function' or
'path.to.ClassBasedView').
"""
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):
def __init__(self, regex, urlconf_name, default_kwargs=None, app_name=None, namespace=None):
LocaleRegexProvider.__init__(self, regex)
# urlconf_name is the dotted Python path to the module defining
# urlpatterns. It may also be an object with an urlpatterns attribute
# or urlpatterns itself.
self.urlconf_name = urlconf_name
self.callback = None
self.default_kwargs = default_kwargs or {}
self.namespace = namespace
self.app_name = app_name
self._reverse_dict = {}
self._namespace_dict = {}
self._app_dict = {}
# set of dotted paths to all functions and classes that are used in
# urlpatterns
self._callback_strs = set()
self._populated = False
def __repr__(self):
if isinstance(self.urlconf_name, list) and len(self.urlconf_name):
# Don't bother to output the whole list, it can be huge
urlconf_repr = '<%s list>' % self.urlconf_name[0].__class__.__name__
else:
urlconf_repr = repr(self.urlconf_name)
return str('<%s %s (%s:%s) %s>') % (
self.__class__.__name__, urlconf_repr, self.app_name,
self.namespace, self.regex.pattern)
def _populate(self):
lookups = MultiValueDict()
namespaces = {}
apps = {}
language_code = get_language()
for pattern in reversed(self.url_patterns):
if isinstance(pattern, RegexURLPattern):
self._callback_strs.add(pattern.lookup_str)
p_pattern = pattern.regex.pattern
if p_pattern.startswith('^'):
p_pattern = p_pattern[1:]
if isinstance(pattern, RegexURLResolver):
if pattern.namespace:
namespaces[pattern.namespace] = (p_pattern, pattern)
if pattern.app_name:
apps.setdefault(pattern.app_name, []).append(pattern.namespace)
else:
parent_pat = pattern.regex.pattern
for name in pattern.reverse_dict:
for matches, pat, defaults in pattern.reverse_dict.getlist(name):
new_matches = normalize(parent_pat + pat)
lookups.appendlist(
name,
(
new_matches,
p_pattern + pat,
dict(defaults, **pattern.default_kwargs),
)
)
for namespace, (prefix, sub_pattern) in pattern.namespace_dict.items():
namespaces[namespace] = (p_pattern + prefix, sub_pattern)
for app_name, namespace_list in pattern.app_dict.items():
apps.setdefault(app_name, []).extend(namespace_list)
self._callback_strs.update(pattern._callback_strs)
else:
bits = normalize(p_pattern)
lookups.appendlist(pattern.callback, (bits, p_pattern, pattern.default_args))
if pattern.name is not None:
lookups.appendlist(pattern.name, (bits, p_pattern, pattern.default_args))
self._reverse_dict[language_code] = lookups
self._namespace_dict[language_code] = namespaces
self._app_dict[language_code] = apps
self._populated = True
@property
def reverse_dict(self):
language_code = get_language()
if language_code not in self._reverse_dict:
self._populate()
return self._reverse_dict[language_code]
@property
def namespace_dict(self):
language_code = get_language()
if language_code not in self._namespace_dict:
self._populate()
return self._namespace_dict[language_code]
@property
def app_dict(self):
language_code = get_language()
if language_code not in self._app_dict:
self._populate()
return self._app_dict[language_code]
def _is_callback(self, name):
if not self._populated:
self._populate()
return name in self._callback_strs
def resolve(self, path):
path = force_text(path) # path may be a reverse_lazy object
tried = []
match = self.regex.search(path)
if match:
new_path = path[match.end():]
for pattern in self.url_patterns:
try:
sub_match = pattern.resolve(new_path)
except Resolver404 as e:
sub_tried = e.args[0].get('tried')
if sub_tried is not None:
tried.extend([pattern] + t for t in sub_tried)
else:
tried.append([pattern])
else:
if sub_match:
# Merge captured arguments in match with submatch
sub_match_dict = dict(match.groupdict(), **self.default_kwargs)
sub_match_dict.update(sub_match.kwargs)
# If there are *any* named groups, ignore all non-named groups.
# Otherwise, pass all non-named arguments as positional arguments.
sub_match_args = sub_match.args
if not sub_match_dict:
sub_match_args = match.groups() + sub_match.args
return ResolverMatch(
sub_match.func,
sub_match_args,
sub_match_dict,
sub_match.url_name,
[self.app_name] + sub_match.app_names,
[self.namespace] + sub_match.namespaces
)
tried.append([pattern])
raise Resolver404({'tried': tried, 'path': new_path})
raise Resolver404({'path': path})
@cached_property
def urlconf_module(self):
if isinstance(self.urlconf_name, six.string_types):
return import_module(self.urlconf_name)
else:
return self.urlconf_name
@cached_property
def url_patterns(self):
# urlconf_module might be a valid set of patterns, so we default to it
patterns = getattr(self.urlconf_module, "urlpatterns", self.urlconf_module)
try:
iter(patterns)
except TypeError:
msg = (
"The included URLconf '{name}' does not appear to have any "
"patterns in it. If you see valid patterns in the file then "
"the issue is probably caused by a circular import."
)
raise ImproperlyConfigured(msg.format(name=self.urlconf_name))
return patterns
def resolve_error_handler(self, view_type):
callback = getattr(self.urlconf_module, 'handler%s' % view_type, None)
if not callback:
# No handler specified in file; use default
# Lazy import, since django.urls imports this file
from django.conf import urls
callback = getattr(urls, 'handler%s' % view_type)
return get_callable(callback), {}
def _reverse_with_prefix(self, lookup_view, _prefix, *args, **kwargs):
if args and kwargs:
raise ValueError("Don't mix *args and **kwargs in call to reverse()!")
text_args = [force_text(v) for v in args]
text_kwargs = {k: force_text(v) for (k, v) in kwargs.items()}
if not self._populated:
self._populate()
possibilities = self.reverse_dict.getlist(lookup_view)
for possibility, pattern, defaults in possibilities:
for result, params in possibility:
if args:
if len(args) != len(params):
continue
candidate_subs = dict(zip(params, text_args))
else:
if (set(kwargs.keys()) | set(defaults.keys()) != set(params) |
set(defaults.keys())):
continue
matches = True
for k, v in defaults.items():
if kwargs.get(k, v) != v:
matches = False
break
if not matches:
continue
candidate_subs = text_kwargs
# WSGI provides decoded URLs, without %xx escapes, and the URL
# resolver operates on such URLs. First substitute arguments
# without quoting to build a decoded URL and look for a match.
# Then, if we have a match, redo the substitution with quoted
# arguments in order to return a properly encoded URL.
candidate_pat = _prefix.replace('%', '%%') + result
if re.search('^%s%s' % (re.escape(_prefix), pattern), candidate_pat % candidate_subs, re.UNICODE):
# safe characters from `pchar` definition of RFC 3986
url = urlquote(candidate_pat % candidate_subs, safe=RFC3986_SUBDELIMS + str('/~:@'))
# Don't allow construction of scheme relative urls.
if url.startswith('//'):
url = '/%%2F%s' % url[2:]
return url
# lookup_view can be URL name or callable, but callables are not
# friendly in error messages.
m = getattr(lookup_view, '__module__', None)
n = getattr(lookup_view, '__name__', None)
if m is not None and n is not None:
lookup_view_s = "%s.%s" % (m, n)
else:
lookup_view_s = lookup_view
patterns = [pattern for (possibility, pattern, defaults) in possibilities]
raise NoReverseMatch("Reverse for '%s' with arguments '%s' and keyword "
"arguments '%s' not found. %d pattern(s) tried: %s" %
(lookup_view_s, args, kwargs, len(patterns), patterns))
class LocaleRegexURLResolver(RegexURLResolver):
"""
A URL resolver that always matches the active language code as URL prefix.
Rather than taking a regex argument, we just override the ``regex``
function to always return the active language-code as regex.
"""
def __init__(self, urlconf_name, default_kwargs=None, app_name=None, namespace=None):
super(LocaleRegexURLResolver, self).__init__(
None, urlconf_name, default_kwargs, app_name, namespace)
@property
def regex(self):
language_code = get_language()
if language_code not in self._regex_dict:
regex_compiled = re.compile('^%s/' % language_code, re.UNICODE)
self._regex_dict[language_code] = regex_compiled
return self._regex_dict[language_code]
def resolve(path, urlconf=None):
if urlconf is None:
urlconf = get_urlconf()
return get_resolver(urlconf).resolve(path)
def reverse(viewname, urlconf=None, args=None, kwargs=None, current_app=None):
if urlconf is None:
urlconf = get_urlconf()
resolver = get_resolver(urlconf)
args = args or []
kwargs = kwargs or {}
prefix = get_script_prefix()
if not isinstance(viewname, six.string_types):
view = viewname
else:
parts = viewname.split(':')
parts.reverse()
view = parts[0]
path = parts[1:]
if current_app:
current_path = current_app.split(':')
current_path.reverse()
else:
current_path = None
resolved_path = []
ns_pattern = ''
while path:
ns = path.pop()
current_ns = current_path.pop() if current_path else None
# Lookup the name to see if it could be an app identifier
try:
app_list = resolver.app_dict[ns]
# Yes! Path part matches an app in the current Resolver
if current_ns and current_ns in app_list:
# If we are reversing for a particular app,
# use that namespace
ns = current_ns
elif ns not in app_list:
# The name isn't shared by one of the instances
# (i.e., the default) so just pick the first instance
# as the default.
ns = app_list[0]
except KeyError:
pass
if ns != current_ns:
current_path = None
try:
extra, resolver = resolver.namespace_dict[ns]
resolved_path.append(ns)
ns_pattern = ns_pattern + extra
except KeyError as key:
if resolved_path:
raise NoReverseMatch(
"%s is not a registered namespace inside '%s'" %
(key, ':'.join(resolved_path)))
else:
raise NoReverseMatch("%s is not a registered namespace" %
key)
if ns_pattern:
resolver = get_ns_resolver(ns_pattern, resolver)
return force_text(iri_to_uri(resolver._reverse_with_prefix(view, prefix, *args, **kwargs)))
reverse_lazy = lazy(reverse, six.text_type)
def clear_url_caches():
get_callable.cache_clear()
get_resolver.cache_clear()
get_ns_resolver.cache_clear()
def set_script_prefix(prefix):
"""
Sets the script prefix for the current thread.
"""
if not prefix.endswith('/'):
prefix += '/'
_prefixes.value = prefix
def get_script_prefix():
"""
Returns the currently active script prefix. Useful for client code that
wishes to construct their own URLs manually (although accessing the request
instance is normally going to be a lot cleaner).
"""
return getattr(_prefixes, "value", '/')
def clear_script_prefix():
"""
Unsets the script prefix for the current thread.
"""
try:
del _prefixes.value
except AttributeError:
pass
def set_urlconf(urlconf_name):
"""
Sets the URLconf for the current thread (overriding the default one in
settings). Set to None to revert back to the default.
"""
if urlconf_name:
_urlconfs.value = urlconf_name
else:
if hasattr(_urlconfs, "value"):
del _urlconfs.value
def get_urlconf(default=None):
"""
Returns the root URLconf to use for the current thread if it has been
changed from the default one.
"""
return getattr(_urlconfs, "value", default)
def is_valid_path(path, urlconf=None):
"""
Returns True if the given path resolves against the default URL resolver,
False otherwise.
This is a convenience method to make working with "is this a match?" cases
easier, avoiding unnecessarily indented try...except blocks.
"""
try:
resolve(path, urlconf)
return True
except Resolver404:
return False
def translate_url(url, lang_code):
"""
Given a URL (absolute or relative), try to get its translated version in
the `lang_code` language (either by i18n_patterns or by translated regex).
Return the original URL if no translated version is found.
"""
parsed = urlsplit(url)
try:
match = resolve(parsed.path)
except Resolver404:
pass
else:
to_be_reversed = "%s:%s" % (match.namespace, match.url_name) if match.namespace else match.url_name
with override(lang_code):
try:
url = reverse(to_be_reversed, args=match.args, kwargs=match.kwargs)
except NoReverseMatch:
pass
else:
url = urlunsplit((parsed.scheme, parsed.netloc, url, parsed.query, parsed.fragment))
return url
warnings.warn(
"Importing from django.core.urlresolvers is deprecated in favor of "
"django.urls.", RemovedInDjango20Warning, stacklevel=2
)

View File

@ -26,15 +26,15 @@ from django.db.models.fields.related import ( # NOQA isort:skip
def permalink(func):
"""
Decorator that calls urlresolvers.reverse() to return a URL using
parameters returned by the decorated function "func".
Decorator that calls urls.reverse() to return a URL using parameters
returned by the decorated function "func".
"func" should be a function that returns a tuple in one of the
following formats:
(viewname, viewargs)
(viewname, viewargs, viewkwargs)
"""
from django.core.urlresolvers import reverse
from django.urls import reverse
@wraps(func)
def inner(*args, **kwargs):

View File

@ -3,9 +3,9 @@ import re
from django import http
from django.conf import settings
from django.core import urlresolvers
from django.core.exceptions import PermissionDenied
from django.core.mail import mail_managers
from django.urls import is_valid_path
from django.utils.cache import get_conditional_response, set_response_etag
from django.utils.encoding import force_text
from django.utils.six.moves.urllib.parse import urlparse
@ -74,8 +74,8 @@ class CommonMiddleware(object):
if settings.APPEND_SLASH and not request.get_full_path().endswith('/'):
urlconf = getattr(request, 'urlconf', None)
return (
not urlresolvers.is_valid_path(request.path_info, urlconf)
and urlresolvers.is_valid_path('%s/' % request.path_info, urlconf)
not is_valid_path(request.path_info, urlconf)
and is_valid_path('%s/' % request.path_info, urlconf)
)
return False

View File

@ -10,7 +10,7 @@ import logging
import re
from django.conf import settings
from django.core.urlresolvers import get_callable
from django.urls import get_callable
from django.utils.cache import patch_vary_headers
from django.utils.crypto import constant_time_compare, get_random_string
from django.utils.encoding import force_text

View File

@ -1,10 +1,10 @@
"This is the locale selecting middleware that will look at accept headers"
from django.conf import settings
from django.core.urlresolvers import (
from django.http import HttpResponseRedirect
from django.urls import (
LocaleRegexURLResolver, get_resolver, get_script_prefix, is_valid_path,
)
from django.http import HttpResponseRedirect
from django.utils import translation
from django.utils.cache import patch_vary_headers
from django.utils.functional import cached_property

View File

@ -3,7 +3,6 @@ This module collects helper functions and classes that "span" multiple levels
of MVC. In other words, these functions/classes introduce controlled coupling
for convenience's sake.
"""
from django.core import urlresolvers
from django.db.models.base import ModelBase
from django.db.models.manager import Manager
from django.db.models.query import QuerySet
@ -11,6 +10,7 @@ from django.http import (
Http404, HttpResponse, HttpResponsePermanentRedirect, HttpResponseRedirect,
)
from django.template import loader
from django.urls import NoReverseMatch, reverse
from django.utils import six
from django.utils.encoding import force_text
from django.utils.functional import Promise
@ -43,8 +43,8 @@ def redirect(to, *args, **kwargs):
* A model: the model's `get_absolute_url()` function will be called.
* A view name, possibly with arguments: `urlresolvers.reverse()` will
be used to reverse-resolve the name.
* A view name, possibly with arguments: `urls.reverse()` will be used
to reverse-resolve the name.
* A URL, which will be used as-is for the redirect location.
@ -123,8 +123,8 @@ def resolve_url(to, *args, **kwargs):
* A model: the model's `get_absolute_url()` function will be called.
* A view name, possibly with arguments: `urlresolvers.reverse()` will
be used to reverse-resolve the name.
* A view name, possibly with arguments: `urls.reverse()` will be used
to reverse-resolve the name.
* A URL, which will be returned as-is.
"""
@ -144,8 +144,8 @@ def resolve_url(to, *args, **kwargs):
# Next try a reverse URL resolution.
try:
return urlresolvers.reverse(to, args=args, kwargs=kwargs)
except urlresolvers.NoReverseMatch:
return reverse(to, args=args, kwargs=kwargs)
except NoReverseMatch:
# If this is a callable, re-raise.
if callable(to):
raise

View File

@ -426,7 +426,7 @@ class URLNode(Node):
self.asvar = asvar
def render(self, context):
from django.core.urlresolvers import reverse, NoReverseMatch
from django.urls import reverse, NoReverseMatch
args = [arg.resolve(context) for arg in self.args]
kwargs = {
smart_text(k, 'ascii'): v.resolve(context)

View File

@ -11,7 +11,6 @@ from io import BytesIO
from django.apps import apps
from django.conf import settings
from django.core import urlresolvers
from django.core.handlers.base import BaseHandler
from django.core.handlers.wsgi import ISO_8859_1, UTF_8, WSGIRequest
from django.core.signals import (
@ -22,6 +21,7 @@ from django.http import HttpRequest, QueryDict, SimpleCookie
from django.template import TemplateDoesNotExist
from django.test import signals
from django.test.utils import ContextList
from django.urls import resolve
from django.utils import six
from django.utils.encoding import force_bytes, force_str, uri_to_iri
from django.utils.functional import SimpleLazyObject, curry
@ -477,8 +477,7 @@ class Client(RequestFactory):
response.json = curry(self._parse_json, response)
# Attach the ResolverMatch instance to the response
response.resolver_match = SimpleLazyObject(
lambda: urlresolvers.resolve(request['PATH_INFO']))
response.resolver_match = SimpleLazyObject(lambda: resolve(request['PATH_INFO']))
# Flatten a single context. Not really necessary anymore thanks to
# the __getattr__ flattening in ContextList, but has some edge-case

View File

@ -145,7 +145,7 @@ def complex_setting_changed(**kwargs):
@receiver(setting_changed)
def root_urlconf_changed(**kwargs):
if kwargs['setting'] == 'ROOT_URLCONF':
from django.core.urlresolvers import clear_url_caches, set_urlconf
from django.urls import clear_url_caches, set_urlconf
clear_url_caches()
set_urlconf(None)

View File

@ -12,11 +12,11 @@ from django.apps import apps
from django.conf import UserSettingsHolder, settings
from django.core import mail
from django.core.signals import request_started
from django.core.urlresolvers import get_script_prefix, set_script_prefix
from django.db import reset_queries
from django.http import request
from django.template import Template
from django.test.signals import setting_changed, template_rendered
from django.urls import get_script_prefix, set_script_prefix
from django.utils import six
from django.utils.decorators import ContextDecorator
from django.utils.encoding import force_str

20
django/urls/__init__.py Normal file
View File

@ -0,0 +1,20 @@
from .base import (
clear_script_prefix, clear_url_caches, get_script_prefix, get_urlconf,
is_valid_path, resolve, reverse, reverse_lazy, set_script_prefix,
set_urlconf, translate_url,
)
from .exceptions import NoReverseMatch, Resolver404
from .resolvers import (
LocaleRegexProvider, LocaleRegexURLResolver, RegexURLPattern,
RegexURLResolver, ResolverMatch, get_ns_resolver, get_resolver,
)
from .utils import get_callable, get_mod_func
__all__ = [
'LocaleRegexProvider', 'LocaleRegexURLResolver', 'NoReverseMatch',
'RegexURLPattern', 'RegexURLResolver', 'Resolver404', 'ResolverMatch',
'clear_script_prefix', 'clear_url_caches', 'get_callable', 'get_mod_func',
'get_ns_resolver', 'get_resolver', 'get_script_prefix', 'get_urlconf',
'is_valid_path', 'resolve', 'reverse', 'reverse_lazy', 'set_script_prefix',
'set_urlconf', 'translate_url',
]

185
django/urls/base.py Normal file
View File

@ -0,0 +1,185 @@
from __future__ import unicode_literals
from threading import local
from django.utils import six
from django.utils.encoding import force_text, iri_to_uri
from django.utils.functional import lazy
from django.utils.six.moves.urllib.parse import urlsplit, urlunsplit
from django.utils.translation import override
from .exceptions import NoReverseMatch, Resolver404
from .resolvers import get_ns_resolver, get_resolver
from .utils import get_callable
# SCRIPT_NAME prefixes for each thread are stored here. If there's no entry for
# the current thread (which is the only one we ever access), it is assumed to
# be empty.
_prefixes = local()
# Overridden URLconfs for each thread are stored here.
_urlconfs = local()
def resolve(path, urlconf=None):
if urlconf is None:
urlconf = get_urlconf()
return get_resolver(urlconf).resolve(path)
def reverse(viewname, urlconf=None, args=None, kwargs=None, current_app=None):
if urlconf is None:
urlconf = get_urlconf()
resolver = get_resolver(urlconf)
args = args or []
kwargs = kwargs or {}
prefix = get_script_prefix()
if not isinstance(viewname, six.string_types):
view = viewname
else:
parts = viewname.split(':')
parts.reverse()
view = parts[0]
path = parts[1:]
if current_app:
current_path = current_app.split(':')
current_path.reverse()
else:
current_path = None
resolved_path = []
ns_pattern = ''
while path:
ns = path.pop()
current_ns = current_path.pop() if current_path else None
# Lookup the name to see if it could be an app identifier.
try:
app_list = resolver.app_dict[ns]
# Yes! Path part matches an app in the current Resolver.
if current_ns and current_ns in app_list:
# If we are reversing for a particular app, use that
# namespace.
ns = current_ns
elif ns not in app_list:
# The name isn't shared by one of the instances (i.e.,
# the default) so pick the first instance as the default.
ns = app_list[0]
except KeyError:
pass
if ns != current_ns:
current_path = None
try:
extra, resolver = resolver.namespace_dict[ns]
resolved_path.append(ns)
ns_pattern = ns_pattern + extra
except KeyError as key:
if resolved_path:
raise NoReverseMatch(
"%s is not a registered namespace inside '%s'" %
(key, ':'.join(resolved_path))
)
else:
raise NoReverseMatch("%s is not a registered namespace" % key)
if ns_pattern:
resolver = get_ns_resolver(ns_pattern, resolver)
return force_text(iri_to_uri(resolver._reverse_with_prefix(view, prefix, *args, **kwargs)))
reverse_lazy = lazy(reverse, six.text_type)
def clear_url_caches():
get_callable.cache_clear()
get_resolver.cache_clear()
get_ns_resolver.cache_clear()
def set_script_prefix(prefix):
"""
Set the script prefix for the current thread.
"""
if not prefix.endswith('/'):
prefix += '/'
_prefixes.value = prefix
def get_script_prefix():
"""
Return the currently active script prefix. Useful for client code that
wishes to construct their own URLs manually (although accessing the request
instance is normally going to be a lot cleaner).
"""
return getattr(_prefixes, "value", '/')
def clear_script_prefix():
"""
Unset the script prefix for the current thread.
"""
try:
del _prefixes.value
except AttributeError:
pass
def set_urlconf(urlconf_name):
"""
Set the URLconf for the current thread (overriding the default one in
settings). If urlconf_name is None, revert back to the default.
"""
if urlconf_name:
_urlconfs.value = urlconf_name
else:
if hasattr(_urlconfs, "value"):
del _urlconfs.value
def get_urlconf(default=None):
"""
Return the root URLconf to use for the current thread if it has been
changed from the default one.
"""
return getattr(_urlconfs, "value", default)
def is_valid_path(path, urlconf=None):
"""
Return True if the given path resolves against the default URL resolver,
False otherwise. This is a convenience method to make working with "is
this a match?" cases easier, avoiding try...except blocks.
"""
from django.urls.base import resolve
try:
resolve(path, urlconf)
return True
except Resolver404:
return False
def translate_url(url, lang_code):
"""
Given a URL (absolute or relative), try to get its translated version in
the `lang_code` language (either by i18n_patterns or by translated regex).
Return the original URL if no translated version is found.
"""
from django.urls import resolve, reverse
parsed = urlsplit(url)
try:
match = resolve(parsed.path)
except Resolver404:
pass
else:
to_be_reversed = "%s:%s" % (match.namespace, match.url_name) if match.namespace else match.url_name
with override(lang_code):
try:
url = reverse(to_be_reversed, args=match.args, kwargs=match.kwargs)
except NoReverseMatch:
pass
else:
url = urlunsplit((parsed.scheme, parsed.netloc, url, parsed.query, parsed.fragment))
return url

11
django/urls/exceptions.py Normal file
View File

@ -0,0 +1,11 @@
from __future__ import unicode_literals
from django.http import Http404
class Resolver404(Http404):
pass
class NoReverseMatch(Exception):
pass

393
django/urls/resolvers.py Normal file
View File

@ -0,0 +1,393 @@
"""
This module converts requested URLs to callback view functions.
RegexURLResolver is the main class here. Its resolve() method takes a URL (as
a string) and returns a ResolverMatch object which provides access to all
attributes of the resolved URL match.
"""
from __future__ import unicode_literals
import functools
import re
from importlib import import_module
from django.core.exceptions import ImproperlyConfigured
from django.utils import lru_cache, six
from django.utils.datastructures import MultiValueDict
from django.utils.encoding import force_str, force_text
from django.utils.functional import cached_property
from django.utils.http import RFC3986_SUBDELIMS, urlquote
from django.utils.regex_helper import normalize
from django.utils.translation import get_language
from .exceptions import NoReverseMatch, Resolver404
from .utils import get_callable
class ResolverMatch(object):
def __init__(self, func, args, kwargs, url_name=None, app_names=None, namespaces=None):
self.func = func
self.args = args
self.kwargs = kwargs
self.url_name = url_name
# If a URLRegexResolver doesn't have a namespace or app_name, it passes
# in an empty value.
self.app_names = [x for x in app_names if x] if app_names else []
self.app_name = ':'.join(self.app_names)
self.namespaces = [x for x in namespaces if x] if namespaces else []
self.namespace = ':'.join(self.namespaces)
if not hasattr(func, '__name__'):
# A class-based view
self._func_path = '.'.join([func.__class__.__module__, func.__class__.__name__])
else:
# A function-based view
self._func_path = '.'.join([func.__module__, func.__name__])
view_path = url_name or self._func_path
self.view_name = ':'.join(self.namespaces + [view_path])
def __getitem__(self, index):
return (self.func, self.args, self.kwargs)[index]
def __repr__(self):
return "ResolverMatch(func=%s, args=%s, kwargs=%s, url_name=%s, app_names=%s, namespaces=%s)" % (
self._func_path, self.args, self.kwargs, self.url_name,
self.app_names, self.namespaces,
)
@lru_cache.lru_cache(maxsize=None)
def get_resolver(urlconf=None):
if urlconf is None:
from django.conf import settings
urlconf = settings.ROOT_URLCONF
return RegexURLResolver(r'^/', urlconf)
@lru_cache.lru_cache(maxsize=None)
def get_ns_resolver(ns_pattern, resolver):
# Build a namespaced resolver for the given parent URLconf pattern.
# This makes it possible to have captured parameters in the parent
# URLconf pattern.
ns_resolver = RegexURLResolver(ns_pattern, resolver.url_patterns)
return RegexURLResolver(r'^/', [ns_resolver])
class LocaleRegexProvider(object):
"""
A mixin to provide a default regex property which can vary by active
language.
"""
def __init__(self, regex):
# regex is either a string representing a regular expression, or a
# translatable string (using ugettext_lazy) representing a regular
# expression.
self._regex = regex
self._regex_dict = {}
@property
def regex(self):
"""
Return a compiled regular expression based on the activate language.
"""
language_code = get_language()
if language_code not in self._regex_dict:
regex = self._regex if isinstance(self._regex, six.string_types) else force_text(self._regex)
try:
compiled_regex = re.compile(regex, re.UNICODE)
except re.error as e:
raise ImproperlyConfigured(
'"%s" is not a valid regular expression: %s' %
(regex, six.text_type(e))
)
self._regex_dict[language_code] = compiled_regex
return self._regex_dict[language_code]
class RegexURLPattern(LocaleRegexProvider):
def __init__(self, regex, callback, default_args=None, name=None):
LocaleRegexProvider.__init__(self, regex)
self.callback = callback # the view
self.default_args = default_args or {}
self.name = name
def __repr__(self):
return force_str('<%s %s %s>' % (self.__class__.__name__, self.name, self.regex.pattern))
def resolve(self, path):
match = self.regex.search(path)
if match:
# If there are any named groups, use those as kwargs, ignoring
# non-named groups. Otherwise, pass all non-named arguments as
# positional arguments.
kwargs = match.groupdict()
args = () if kwargs else match.groups()
# In both cases, pass any extra_kwargs as **kwargs.
kwargs.update(self.default_args)
return ResolverMatch(self.callback, args, kwargs, self.name)
@cached_property
def lookup_str(self):
"""
A string that identifies the view (e.g. 'path.to.view_function' or
'path.to.ClassBasedView').
"""
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):
def __init__(self, regex, urlconf_name, default_kwargs=None, app_name=None, namespace=None):
LocaleRegexProvider.__init__(self, regex)
# urlconf_name is the dotted Python path to the module defining
# urlpatterns. It may also be an object with an urlpatterns attribute
# or urlpatterns itself.
self.urlconf_name = urlconf_name
self.callback = None
self.default_kwargs = default_kwargs or {}
self.namespace = namespace
self.app_name = app_name
self._reverse_dict = {}
self._namespace_dict = {}
self._app_dict = {}
# set of dotted paths to all functions and classes that are used in
# urlpatterns
self._callback_strs = set()
self._populated = False
def __repr__(self):
if isinstance(self.urlconf_name, list) and len(self.urlconf_name):
# Don't bother to output the whole list, it can be huge
urlconf_repr = '<%s list>' % self.urlconf_name[0].__class__.__name__
else:
urlconf_repr = repr(self.urlconf_name)
return str('<%s %s (%s:%s) %s>') % (
self.__class__.__name__, urlconf_repr, self.app_name,
self.namespace, self.regex.pattern,
)
def _populate(self):
lookups = MultiValueDict()
namespaces = {}
apps = {}
language_code = get_language()
for pattern in reversed(self.url_patterns):
if isinstance(pattern, RegexURLPattern):
self._callback_strs.add(pattern.lookup_str)
p_pattern = pattern.regex.pattern
if p_pattern.startswith('^'):
p_pattern = p_pattern[1:]
if isinstance(pattern, RegexURLResolver):
if pattern.namespace:
namespaces[pattern.namespace] = (p_pattern, pattern)
if pattern.app_name:
apps.setdefault(pattern.app_name, []).append(pattern.namespace)
else:
parent_pat = pattern.regex.pattern
for name in pattern.reverse_dict:
for matches, pat, defaults in pattern.reverse_dict.getlist(name):
new_matches = normalize(parent_pat + pat)
lookups.appendlist(
name,
(
new_matches,
p_pattern + pat,
dict(defaults, **pattern.default_kwargs),
)
)
for namespace, (prefix, sub_pattern) in pattern.namespace_dict.items():
namespaces[namespace] = (p_pattern + prefix, sub_pattern)
for app_name, namespace_list in pattern.app_dict.items():
apps.setdefault(app_name, []).extend(namespace_list)
self._callback_strs.update(pattern._callback_strs)
else:
bits = normalize(p_pattern)
lookups.appendlist(pattern.callback, (bits, p_pattern, pattern.default_args))
if pattern.name is not None:
lookups.appendlist(pattern.name, (bits, p_pattern, pattern.default_args))
self._reverse_dict[language_code] = lookups
self._namespace_dict[language_code] = namespaces
self._app_dict[language_code] = apps
self._populated = True
@property
def reverse_dict(self):
language_code = get_language()
if language_code not in self._reverse_dict:
self._populate()
return self._reverse_dict[language_code]
@property
def namespace_dict(self):
language_code = get_language()
if language_code not in self._namespace_dict:
self._populate()
return self._namespace_dict[language_code]
@property
def app_dict(self):
language_code = get_language()
if language_code not in self._app_dict:
self._populate()
return self._app_dict[language_code]
def _is_callback(self, name):
if not self._populated:
self._populate()
return name in self._callback_strs
def resolve(self, path):
path = force_text(path) # path may be a reverse_lazy object
tried = []
match = self.regex.search(path)
if match:
new_path = path[match.end():]
for pattern in self.url_patterns:
try:
sub_match = pattern.resolve(new_path)
except Resolver404 as e:
sub_tried = e.args[0].get('tried')
if sub_tried is not None:
tried.extend([pattern] + t for t in sub_tried)
else:
tried.append([pattern])
else:
if sub_match:
# Merge captured arguments in match with submatch
sub_match_dict = dict(match.groupdict(), **self.default_kwargs)
sub_match_dict.update(sub_match.kwargs)
# If there are *any* named groups, ignore all non-named groups.
# Otherwise, pass all non-named arguments as positional arguments.
sub_match_args = sub_match.args
if not sub_match_dict:
sub_match_args = match.groups() + sub_match.args
return ResolverMatch(
sub_match.func,
sub_match_args,
sub_match_dict,
sub_match.url_name,
[self.app_name] + sub_match.app_names,
[self.namespace] + sub_match.namespaces,
)
tried.append([pattern])
raise Resolver404({'tried': tried, 'path': new_path})
raise Resolver404({'path': path})
@cached_property
def urlconf_module(self):
if isinstance(self.urlconf_name, six.string_types):
return import_module(self.urlconf_name)
else:
return self.urlconf_name
@cached_property
def url_patterns(self):
# urlconf_module might be a valid set of patterns, so we default to it
patterns = getattr(self.urlconf_module, "urlpatterns", self.urlconf_module)
try:
iter(patterns)
except TypeError:
msg = (
"The included URLconf '{name}' does not appear to have any "
"patterns in it. If you see valid patterns in the file then "
"the issue is probably caused by a circular import."
)
raise ImproperlyConfigured(msg.format(name=self.urlconf_name))
return patterns
def resolve_error_handler(self, view_type):
callback = getattr(self.urlconf_module, 'handler%s' % view_type, None)
if not callback:
# No handler specified in file; use lazy import, since
# django.conf.urls imports this file.
from django.conf import urls
callback = getattr(urls, 'handler%s' % view_type)
return get_callable(callback), {}
def _reverse_with_prefix(self, lookup_view, _prefix, *args, **kwargs):
if args and kwargs:
raise ValueError("Don't mix *args and **kwargs in call to reverse()!")
text_args = [force_text(v) for v in args]
text_kwargs = {k: force_text(v) for (k, v) in kwargs.items()}
if not self._populated:
self._populate()
possibilities = self.reverse_dict.getlist(lookup_view)
for possibility, pattern, defaults in possibilities:
for result, params in possibility:
if args:
if len(args) != len(params):
continue
candidate_subs = dict(zip(params, text_args))
else:
if (set(kwargs.keys()) | set(defaults.keys()) != set(params) |
set(defaults.keys())):
continue
matches = True
for k, v in defaults.items():
if kwargs.get(k, v) != v:
matches = False
break
if not matches:
continue
candidate_subs = text_kwargs
# WSGI provides decoded URLs, without %xx escapes, and the URL
# resolver operates on such URLs. First substitute arguments
# without quoting to build a decoded URL and look for a match.
# Then, if we have a match, redo the substitution with quoted
# arguments in order to return a properly encoded URL.
candidate_pat = _prefix.replace('%', '%%') + result
if re.search('^%s%s' % (re.escape(_prefix), pattern), candidate_pat % candidate_subs, re.UNICODE):
# safe characters from `pchar` definition of RFC 3986
url = urlquote(candidate_pat % candidate_subs, safe=RFC3986_SUBDELIMS + str('/~:@'))
# Don't allow construction of scheme relative urls.
if url.startswith('//'):
url = '/%%2F%s' % url[2:]
return url
# lookup_view can be URL name or callable, but callables are not
# friendly in error messages.
m = getattr(lookup_view, '__module__', None)
n = getattr(lookup_view, '__name__', None)
if m is not None and n is not None:
lookup_view_s = "%s.%s" % (m, n)
else:
lookup_view_s = lookup_view
patterns = [pattern for (possibility, pattern, defaults) in possibilities]
raise NoReverseMatch(
"Reverse for '%s' with arguments '%s' and keyword "
"arguments '%s' not found. %d pattern(s) tried: %s" %
(lookup_view_s, args, kwargs, len(patterns), patterns)
)
class LocaleRegexURLResolver(RegexURLResolver):
"""
A URL resolver that always matches the active language code as URL prefix.
Rather than taking a regex argument, we just override the ``regex``
function to always return the active language-code as regex.
"""
def __init__(self, urlconf_name, default_kwargs=None, app_name=None, namespace=None):
super(LocaleRegexURLResolver, self).__init__(
None, urlconf_name, default_kwargs, app_name, namespace,
)
@property
def regex(self):
language_code = get_language()
if language_code not in self._regex_dict:
regex_compiled = re.compile('^%s/' % language_code, re.UNICODE)
self._regex_dict[language_code] = regex_compiled
return self._regex_dict[language_code]

64
django/urls/utils.py Normal file
View File

@ -0,0 +1,64 @@
from __future__ import unicode_literals
from importlib import import_module
from django.core.exceptions import ViewDoesNotExist
from django.utils import lru_cache, six
from django.utils.module_loading import module_has_submodule
@lru_cache.lru_cache(maxsize=None)
def get_callable(lookup_view):
"""
Return a callable corresponding to lookup_view.
* If lookup_view is already a callable, return it.
* If lookup_view is a string import path that can be resolved to a callable,
import that callable and return it, otherwise raise an exception
(ImportError or ViewDoesNotExist).
"""
if callable(lookup_view):
return lookup_view
if not isinstance(lookup_view, six.string_types):
raise ViewDoesNotExist("'%s' is not a callable or a dot-notation path" % lookup_view)
mod_name, func_name = get_mod_func(lookup_view)
if not func_name: # No '.' in lookup_view
raise ImportError("Could not import '%s'. The path must be fully qualified." % lookup_view)
try:
mod = import_module(mod_name)
except ImportError:
parentmod, submod = get_mod_func(mod_name)
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:
try:
view_func = getattr(mod, func_name)
except AttributeError:
raise ViewDoesNotExist(
"Could not import '%s'. View does not exist in module %s." %
(lookup_view, mod_name)
)
else:
if not callable(view_func):
raise ViewDoesNotExist(
"Could not import '%s.%s'. View is not callable." %
(mod_name, func_name)
)
return view_func
def get_mod_func(callback):
# Convert 'django.views.news.stories.story_detail' to
# ['django.views.news.stories', 'story_detail']
try:
dot = callback.rindex('.')
except ValueError:
return callback, ''
return callback[:dot], callback[dot + 1:]

View File

@ -5,10 +5,10 @@ import sys
import types
from django.conf import settings
from django.core.urlresolvers import Resolver404, resolve
from django.http import HttpResponse, HttpResponseNotFound
from django.template import Context, Engine, TemplateDoesNotExist
from django.template.defaultfilters import force_escape, pprint
from django.urls import Resolver404, resolve
from django.utils import lru_cache, six, timezone
from django.utils.datastructures import MultiValueDict
from django.utils.encoding import force_bytes, smart_text

View File

@ -5,8 +5,8 @@ from functools import update_wrapper
from django import http
from django.core.exceptions import ImproperlyConfigured
from django.core.urlresolvers import NoReverseMatch, reverse
from django.template.response import TemplateResponse
from django.urls import NoReverseMatch, reverse
from django.utils import six
from django.utils.decorators import classonlymethod

View File

@ -6,8 +6,8 @@ import os
from django import http
from django.apps import apps
from django.conf import settings
from django.core.urlresolvers import translate_url
from django.template import Context, Engine
from django.urls import translate_url
from django.utils import six
from django.utils._os import upath
from django.utils.encoding import smart_text

View File

@ -262,7 +262,7 @@ already been configured).
So, if there is a module containing some code as follows::
from django.conf import settings
from django.core.urlresolvers import get_callable
from django.urls import get_callable
default_foo_view = get_callable(settings.FOO_VIEW)

View File

@ -128,6 +128,8 @@ details on these changes.
* The ``shell --plain`` option will be removed.
* The ``django.core.urlresolvers`` module will be removed.
.. _deprecation-removed-in-1.10:
1.10
@ -152,8 +154,7 @@ details on these changes.
* Using an incorrect count of unpacked values in the ``for`` template tag
will raise an exception rather than fail silently.
* The ability to :func:`~django.core.urlresolvers.reverse` URLs using a dotted
Python path will be removed.
* The ability to reverse URLs using a dotted Python path will be removed.
* Support for :py:mod:`optparse` will be dropped for custom management commands
(replaced by :py:mod:`argparse`).

View File

@ -56,7 +56,7 @@ To get from a URL to a view, Django uses what are known as 'URLconfs'. A
URLconf maps URL patterns (described as regular expressions) to views.
This tutorial provides basic instruction in the use of URLconfs, and you can
refer to :mod:`django.core.urlresolvers` for more information.
refer to :mod:`django.urls` for more information.
Writing more views
==================

View File

@ -71,7 +71,7 @@ create a real version. Add the following to ``polls/views.py``:
from django.shortcuts import get_object_or_404, render
from django.http import HttpResponseRedirect, HttpResponse
from django.core.urlresolvers import reverse
from django.urls import reverse
from .models import Choice, Question
# ...
@ -124,13 +124,13 @@ This code includes a few things we haven't covered yet in this tutorial:
POST data. This tip isn't specific to Django; it's just good Web
development practice.
* We are using the :func:`~django.core.urlresolvers.reverse` function in the
* We are using the :func:`~django.urls.reverse` function in the
:class:`~django.http.HttpResponseRedirect` constructor in this example.
This function helps avoid having to hardcode a URL in the view function.
It is given the name of the view that we want to pass control to and the
variable portion of the URL pattern that points to that view. In this
case, using the URLconf we set up in :doc:`Tutorial 3 </intro/tutorial03>`,
this :func:`~django.core.urlresolvers.reverse` call will return a string like
this :func:`~django.urls.reverse` call will return a string like
::
'/polls/3/results/'
@ -264,7 +264,7 @@ views and use Django's generic views instead. To do so, open the
from django.shortcuts import get_object_or_404, render
from django.http import HttpResponseRedirect
from django.core.urlresolvers import reverse
from django.urls import reverse
from django.views import generic
from .models import Choice, Question

View File

@ -362,7 +362,7 @@ With that ready, we can ask the client to do some work for us::
404
>>> # on the other hand we should expect to find something at '/polls/'
>>> # we'll use 'reverse()' rather than a hardcoded URL
>>> from django.core.urlresolvers import reverse
>>> from django.urls import reverse
>>> response = client.get(reverse('polls:index'))
>>> response.status_code
200
@ -447,7 +447,7 @@ Add the following to ``polls/tests.py``:
.. snippet::
:filename: polls/tests.py
from django.core.urlresolvers import reverse
from django.urls import reverse
and we'll create a shortcut function to create questions as well as a new test
class:

View File

@ -13,7 +13,7 @@ views for displaying drilldown pages for date-based data.
defined as follows in ``myapp/models.py``::
from django.db import models
from django.core.urlresolvers import reverse
from django.urls import reverse
class Article(models.Model):
title = models.CharField(max_length=200)

View File

@ -15,7 +15,7 @@ editing content:
Some of the examples on this page assume that an ``Author`` model has been
defined as follows in ``myapp/models.py``::
from django.core.urlresolvers import reverse
from django.urls import reverse
from django.db import models
class Author(models.Model):
@ -227,7 +227,7 @@ DeleteView
**Example myapp/views.py**::
from django.views.generic.edit import DeleteView
from django.core.urlresolvers import reverse_lazy
from django.urls import reverse_lazy
from myapp.models import Author
class AuthorDelete(DeleteView):

View File

@ -1252,7 +1252,7 @@ subclass::
For example::
from django.contrib import admin
from django.core.urlresolvers import reverse
from django.urls import reverse
class PersonAdmin(admin.ModelAdmin):
def view_on_site(self, obj):
@ -2883,9 +2883,9 @@ So - if you wanted to get a reference to the Change view for a particular
``Choice`` object (from the polls application) in the default admin, you would
call::
>>> from django.core import urlresolvers
>>> from django.urls import reverse
>>> c = Choice.objects.get(...)
>>> change_url = urlresolvers.reverse('admin:polls_choice_change', args=(c.id,))
>>> change_url = reverse('admin:polls_choice_change', args=(c.id,))
This will find the first registered instance of the admin application
(whatever the instance name), and resolve to the view for changing
@ -2896,8 +2896,7 @@ that instance as a ``current_app`` hint to the reverse call. For example,
if you specifically wanted the admin view from the admin instance named
``custom``, you would need to call::
>>> change_url = urlresolvers.reverse('admin:polls_choice_change',
... args=(c.id,), current_app='custom')
>>> change_url = reverse('admin:polls_choice_change', args=(c.id,), current_app='custom')
For more details, see the documentation on :ref:`reversing namespaced URLs
<topics-http-reversing-url-namespaces>`.

View File

@ -300,13 +300,12 @@ Sitemap for static views
Often you want the search engine crawlers to index views which are neither
object detail pages nor flatpages. The solution is to explicitly list URL
names for these views in ``items`` and call
:func:`~django.core.urlresolvers.reverse` in the ``location`` method of
the sitemap. For example::
names for these views in ``items`` and call :func:`~django.urls.reverse` in
the ``location`` method of the sitemap. For example::
# sitemaps.py
from django.contrib import sitemaps
from django.core.urlresolvers import reverse
from django.urls import reverse
class StaticViewSitemap(sitemaps.Sitemap):
priority = 0.5

View File

@ -53,7 +53,7 @@ This simple example, taken from a hypothetical police beat news site describes
a feed of the latest five news items::
from django.contrib.syndication.views import Feed
from django.core.urlresolvers import reverse
from django.urls import reverse
from policebeat.models import NewsItem
class LatestEntriesFeed(Feed):

View File

@ -84,7 +84,7 @@ Django core exception classes are defined in ``django.core.exceptions``.
.. exception:: ViewDoesNotExist
The :exc:`ViewDoesNotExist` exception is raised by
:mod:`django.core.urlresolvers` when a requested view does not exist.
:mod:`django.urls` when a requested view does not exist.
``MiddlewareNotUsed``
---------------------
@ -142,12 +142,18 @@ or model are classified as ``NON_FIELD_ERRORS``. This constant is used
as a key in dictionaries that otherwise map fields to their respective
list of errors.
.. currentmodule:: django.core.urlresolvers
.. currentmodule:: django.urls
URL Resolver exceptions
=======================
URL Resolver exceptions are defined in ``django.core.urlresolvers``.
URL Resolver exceptions are defined in ``django.urls``.
.. deprecated:: 1.10
In older versions, these exceptions are located in
``django.core.urlresolvers``. Importing from the old location will continue
to work until Django 2.0.
``Resolver404``
---------------
@ -155,18 +161,17 @@ URL Resolver exceptions are defined in ``django.core.urlresolvers``.
.. exception:: Resolver404
The :exc:`Resolver404` exception is raised by
:func:`django.core.urlresolvers.resolve()` if the path passed to
``resolve()`` doesn't map to a view. It's a subclass of
:class:`django.http.Http404`.
:func:`~django.urls.resolve()` if the path passed to ``resolve()`` doesn't
map to a view. It's a subclass of :class:`django.http.Http404`.
``NoReverseMatch``
------------------
.. exception:: NoReverseMatch
The :exc:`NoReverseMatch` exception is raised by
:mod:`django.core.urlresolvers` when a matching URL in your URLconf
cannot be identified based on the parameters supplied.
The :exc:`NoReverseMatch` exception is raised by :mod:`django.urls` when a
matching URL in your URLconf cannot be identified based on the parameters
supplied.
.. currentmodule:: django.db

View File

@ -672,14 +672,14 @@ For example::
def get_absolute_url(self):
return "/people/%i/" % self.id
(Whilst this code is correct and simple, it may not be the most portable way to
write this kind of method. The :func:`~django.core.urlresolvers.reverse`
function is usually the best approach.)
While this code is correct and simple, it may not be the most portable way to
to write this kind of method. The :func:`~django.urls.reverse` function is
usually the best approach.
For example::
def get_absolute_url(self):
from django.core.urlresolvers import reverse
from django.urls import reverse
return reverse('people.views.details', args=[str(self.id)])
One place Django uses ``get_absolute_url()`` is in the admin app. If an object

View File

@ -160,11 +160,11 @@ All attributes should be considered read-only, unless stated otherwise.
.. attribute:: HttpRequest.resolver_match
An instance of :class:`~django.core.urlresolvers.ResolverMatch` representing
the resolved url. This attribute is only set after url resolving took place,
which means it's available in all views but not in middleware methods which
are executed before url resolving takes place (like ``process_request``, you
can use ``process_view`` instead).
An instance of :class:`~django.urls.ResolverMatch` representing the
resolved URL. This attribute is only set after URL resolving took place,
which means it's available in all views but not in middleware methods
which are executed before URL resolving takes place (like
``process_request()``, you can use ``process_view()`` instead).
Attributes set by application code
----------------------------------
@ -175,7 +175,7 @@ application.
.. attribute:: HttpRequest.current_app
The :ttag:`url` template tag will use its value as the ``current_app``
argument to :func:`~django.core.urlresolvers.reverse()`.
argument to :func:`~django.urls.reverse()`.
.. attribute:: HttpRequest.urlconf

View File

@ -1024,8 +1024,8 @@ such as this:
The template tag will output the string ``/clients/client/123/``.
Note that if the URL you're reversing doesn't exist, you'll get an
:exc:`~django.core.urlresolvers.NoReverseMatch` exception raised, which will
cause your site to display an error page.
:exc:`~django.urls.NoReverseMatch` exception raised, which will cause your
site to display an error page.
If you'd like to retrieve a URL without displaying it, you can use a slightly
different call::

View File

@ -290,8 +290,8 @@ Taking care in ``get_absolute_url()``
URLs can only contain ASCII characters. If you're constructing a URL from
pieces of data that might be non-ASCII, be careful to encode the results in a
way that is suitable for a URL. The :func:`~django.core.urlresolvers.reverse`
function handles this for you automatically.
way that is suitable for a URL. The :func:`~django.urls.reverse` function
handles this for you automatically.
If you're constructing a URL manually (i.e., *not* using the ``reverse()``
function), you'll need to take care of the encoding yourself. In this case,

View File

@ -1,8 +1,14 @@
==============================================
``django.core.urlresolvers`` utility functions
==============================================
=================================
``django.urls`` utility functions
=================================
.. module:: django.core.urlresolvers
.. module:: django.urls
.. deprecated:: 1.10
In older versions, these functions are located in
``django.core.urlresolvers``. Importing from the old location will continue
to work until Django 2.0.
reverse()
---------
@ -31,7 +37,7 @@ you can use any of the following to reverse the URL::
If the URL accepts arguments, you may pass them in ``args``. For example::
from django.core.urlresolvers import reverse
from django.urls import reverse
def myview(request):
return HttpResponseRedirect(reverse('arch-summary', args=[1945]))
@ -44,7 +50,7 @@ You can also pass ``kwargs`` instead of ``args``. For example::
``args`` and ``kwargs`` cannot be passed to ``reverse()`` at the same time.
If no match can be made, ``reverse()`` raises a
:class:`~django.core.urlresolvers.NoReverseMatch` exception.
:class:`~django.urls.NoReverseMatch` exception.
The ``reverse()`` function can reverse a large variety of regular expression
patterns for URLs, but not every possible one. The main restriction at the
@ -103,13 +109,12 @@ corresponding view functions. It has the following signature:
.. function:: resolve(path, urlconf=None)
``path`` is the URL path you want to resolve. As with
:func:`~django.core.urlresolvers.reverse`, you don't need to
worry about the ``urlconf`` parameter. The function returns a
:class:`ResolverMatch` object that allows you
to access various meta-data about the resolved URL.
:func:`~django.urls.reverse`, you don't need to worry about the ``urlconf``
parameter. The function returns a :class:`ResolverMatch` object that allows you
to access various metadata about the resolved URL.
If the URL does not resolve, the function raises a
:exc:`~django.core.urlresolvers.Resolver404` exception (a subclass of
:exc:`~django.urls.Resolver404` exception (a subclass of
:class:`~django.http.Http404`) .
.. class:: ResolverMatch
@ -175,10 +180,10 @@ A :class:`ResolverMatch` object can also be assigned to a triple::
func, args, kwargs = resolve('/some/path/')
One possible use of :func:`~django.core.urlresolvers.resolve` would be to test
whether a view would raise a ``Http404`` error before redirecting to it::
One possible use of :func:`~django.urls.resolve` would be to test whether a
view would raise a ``Http404`` error before redirecting to it::
from django.core.urlresolvers import resolve
from django.urls import resolve
from django.http import HttpResponseRedirect, Http404
from django.utils.six.moves.urllib.parse import urlparse
@ -202,12 +207,11 @@ get_script_prefix()
.. function:: get_script_prefix()
Normally, you should always use :func:`~django.core.urlresolvers.reverse` to
define URLs within your application. However, if your application constructs
part of the URL hierarchy itself, you may occasionally need to generate URLs.
In that case, you need to be able to find the base URL of the Django project
within its Web server (normally, :func:`~django.core.urlresolvers.reverse`
takes care of this for you). In that case, you can call
``get_script_prefix()``, which will return the script prefix portion of the URL
for your Django project. If your Django project is at the root of its web
server, this is always ``"/"``.
Normally, you should always use :func:`~django.urls.reverse` to define URLs
within your application. However, if your application constructs part of the
URL hierarchy itself, you may occasionally need to generate URLs. In that
case, you need to be able to find the base URL of the Django project within
its Web server (normally, :func:`~django.urls.reverse` takes care of this for
you). In that case, you can call ``get_script_prefix()``, which will return
the script prefix portion of the URL for your Django project. If your Django
project is at the root of its web server, this is always ``"/"``.

View File

@ -380,11 +380,11 @@ Other new features and changes introduced since Django 1.0 include:
order to allow fine-grained control of when and where the CSRF processing
takes place.
* :func:`~django.core.urlresolvers.reverse` and code which uses it (e.g., the
``{% url %}`` template tag) now works with URLs in Django's administrative
site, provided that the admin URLs are set up via ``include(admin.site.urls)``
(sending admin requests to the ``admin.site.root`` view still works, but URLs
in the admin will not be "reversible" when configured this way).
* ``reverse()`` and code which uses it (e.g., the ``{% url %}`` template tag)
now works with URLs in Django's administrative site, provided that the admin
URLs are set up via ``include(admin.site.urls)`` (sending admin requests to
the ``admin.site.root`` view still works, but URLs in the admin will not be
"reversible" when configured this way).
* The ``include()`` function in Django URLconf modules can now accept sequences
of URL patterns (generated by ``patterns()``) in addition to module names.

View File

@ -460,6 +460,9 @@ Miscellaneous
* The ``shell --plain`` option is deprecated in favor of ``-i python`` or
``--interface python``.
* Importing from the ``django.core.urlresolvers`` module is deprecated in
favor of its new location, :mod:`django.urls`.
.. _removed-features-1.10:
Features removed in 1.10
@ -485,8 +488,8 @@ removed in Django 1.10 (please see the :ref:`deprecation timeline
* Using an incorrect count of unpacked values in the ``for`` template tag
raises an exception rather than failing silently.
* The ability to :func:`~django.core.urlresolvers.reverse` URLs using a dotted
Python path is removed.
* The ability to :func:`~django.urls.reverse` URLs using a dotted Python path
is removed.
* Support for ``optparse`` is dropped for custom management commands.

View File

@ -16,14 +16,12 @@ Django's URL handling is based on a mapping of regex patterns
consists of matching a requested URL against those patterns to
determine the appropriate view to invoke.
Django also provides a convenience function --
:func:`~django.core.urlresolvers.reverse` -- which performs this process
in the opposite direction. The ``reverse()`` function takes
information about a view and returns a URL which would invoke that
view. Use of ``reverse()`` is encouraged for application developers,
as the output of ``reverse()`` is always based on the current URL
patterns, meaning developers do not need to change other code when
making changes to URLs.
Django also provides a convenience function -- ``reverse()`` -- which performs
this process in the opposite direction. The ``reverse()`` function takes
information about a view and returns a URL which would invoke that view. Use
of ``reverse()`` is encouraged for application developers, as the output of
``reverse()`` is always based on the current URL patterns, meaning developers
do not need to change other code when making changes to URLs.
One argument signature for ``reverse()`` is to pass a dotted Python
path to the desired view. In this situation, Django will import the

View File

@ -9,6 +9,5 @@ Django 1.4.12 fixes a regression in the 1.4.11 security release.
Bugfixes
========
* Restored the ability to :meth:`~django.core.urlresolvers.reverse` views
created using :func:`functools.partial()`
(:ticket:`22486`)
* Restored the ability to ``reverse()`` views created using
:func:`functools.partial()` (:ticket:`22486`).

View File

@ -6,8 +6,8 @@ Django 1.4.14 release notes
Django 1.4.14 fixes several security issues in 1.4.13.
:func:`~django.core.urlresolvers.reverse()` could generate URLs pointing to other hosts
=======================================================================================
``reverse()`` could generate URLs pointing to other hosts
=========================================================
In certain situations, URL reversing could generate scheme-relative URLs (URLs
starting with two slashes), which could unexpectedly redirect a user to a

View File

@ -371,8 +371,8 @@ Django 1.4 to store the wizard's state in the user's cookies.
``reverse_lazy``
~~~~~~~~~~~~~~~~
A lazily evaluated version of :func:`django.core.urlresolvers.reverse` was
added to allow using URL reversals before the project's URLconf gets loaded.
A lazily evaluated version of ``reverse()`` was added to allow using URL
reversals before the project's URLconf gets loaded.
Translating URL patterns
~~~~~~~~~~~~~~~~~~~~~~~~

View File

@ -15,14 +15,12 @@ Django's URL handling is based on a mapping of regex patterns
consists of matching a requested URL against those patterns to
determine the appropriate view to invoke.
Django also provides a convenience function --
:func:`~django.core.urlresolvers.reverse` -- which performs this process
in the opposite direction. The ``reverse()`` function takes
information about a view and returns a URL which would invoke that
view. Use of ``reverse()`` is encouraged for application developers,
as the output of ``reverse()`` is always based on the current URL
patterns, meaning developers do not need to change other code when
making changes to URLs.
Django also provides a convenience function -- ``reverse()`` -- which performs
this process in the opposite direction. The ``reverse()`` function takes
information about a view and returns a URL which would invoke that view. Use
of ``reverse()`` is encouraged for application developers, as the output of
``reverse()`` is always based on the current URL patterns, meaning developers
do not need to change other code when making changes to URLs.
One argument signature for ``reverse()`` is to pass a dotted Python
path to the desired view. In this situation, Django will import the

View File

@ -9,5 +9,5 @@ Django 1.5.7 fixes a regression in the 1.5.6 security release.
Bugfixes
========
* Restored the ability to :meth:`~django.core.urlresolvers.reverse` views
created using :func:`functools.partial()` (:ticket:`22486`).
* Restored the ability to ``reverse()`` views created using
:func:`functools.partial()` (:ticket:`22486`).

View File

@ -6,8 +6,8 @@ Django 1.5.9 release notes
Django 1.5.9 fixes several security issues in 1.5.8.
:func:`~django.core.urlresolvers.reverse()` could generate URLs pointing to other hosts
=======================================================================================
``reverse()`` could generate URLs pointing to other hosts
=========================================================
In certain situations, URL reversing could generate scheme-relative URLs (URLs
starting with two slashes), which could unexpectedly redirect a user to a

View File

@ -293,8 +293,8 @@ Django 1.5 also includes several smaller improvements worth noting:
objects fetched into memory. See :meth:`QuerySet.delete()
<django.db.models.query.QuerySet.delete>` for details.
* An instance of :class:`~django.core.urlresolvers.ResolverMatch` is stored on
the request as ``resolver_match``.
* An instance of ``ResolverMatch`` is stored on the request as
``resolver_match``.
* By default, all logging messages reaching the ``django`` logger when
:setting:`DEBUG` is ``True`` are sent to the console (unless you redefine the

View File

@ -15,14 +15,12 @@ Django's URL handling is based on a mapping of regex patterns
consists of matching a requested URL against those patterns to
determine the appropriate view to invoke.
Django also provides a convenience function --
:func:`~django.core.urlresolvers.reverse` -- which performs this process
in the opposite direction. The ``reverse()`` function takes
information about a view and returns a URL which would invoke that
view. Use of ``reverse()`` is encouraged for application developers,
as the output of ``reverse()`` is always based on the current URL
patterns, meaning developers do not need to change other code when
making changes to URLs.
Django also provides a convenience function -- ``reverse()`` -- which performs
this process in the opposite direction. The ``reverse()`` function takes
information about a view and returns a URL which would invoke that view. Use
of ``reverse()`` is encouraged for application developers, as the output of
``reverse()`` is always based on the current URL patterns, meaning developers
do not need to change other code when making changes to URLs.
One argument signature for ``reverse()`` is to pass a dotted Python
path to the desired view. In this situation, Django will import the

View File

@ -13,10 +13,8 @@ Bugfixes
cookie format of Django 1.4 and earlier to facilitate upgrading to 1.6 from
1.4 (:ticket:`22426`).
* Restored the ability to :meth:`~django.core.urlresolvers.reverse` views
created using :func:`functools.partial()`
(:ticket:`22486`).
* Restored the ability to ``reverse()`` views created using
:func:`functools.partial()` (:ticket:`22486`).
* Fixed the ``object_id`` of the ``LogEntry`` that's created after a user
password change in the admin
(:ticket:`22515`).
password change in the admin (:ticket:`22515`).

View File

@ -6,8 +6,8 @@ Django 1.6.6 release notes
Django 1.6.6 fixes several security issues and bugs in 1.6.5.
:func:`~django.core.urlresolvers.reverse()` could generate URLs pointing to other hosts
=======================================================================================
``reverse()`` could generate URLs pointing to other hosts
=========================================================
In certain situations, URL reversing could generate scheme-relative URLs (URLs
starting with two slashes), which could unexpectedly redirect a user to a

View File

@ -583,16 +583,17 @@ be at the end of a line. If they are not, the comments are ignored and
{{ title }}{# Translators: Extracted and associated with 'Welcome' below #}
<h1>{% trans "Welcome" %}</h1>
Quoting in :func:`~django.core.urlresolvers.reverse`
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Quoting in ``reverse()``
~~~~~~~~~~~~~~~~~~~~~~~~
When reversing URLs, Django didn't apply :func:`~django.utils.http.urlquote`
to arguments before interpolating them in URL patterns. This bug is fixed in
Django 1.6. If you worked around this bug by applying URL quoting before
passing arguments to :func:`~django.core.urlresolvers.reverse`, this may
result in double-quoting. If this happens, simply remove the URL quoting from
your code. You will also have to replace special characters in URLs used in
:func:`~django.test.SimpleTestCase.assertRedirects` with their encoded versions.
passing arguments to ``reverse()``, this may result in double-quoting. If this
happens, simply remove the URL quoting from your code. You will also have to
replace special characters in URLs used in
:func:`~django.test.SimpleTestCase.assertRedirects` with their encoded
versions.
Storage of IP addresses in the comments app
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@ -902,12 +903,12 @@ Miscellaneous
stored as ``null``. Previously, storing a ``blank`` value in a field which
did not allow ``null`` would cause a database exception at runtime.
* If a :class:`~django.core.urlresolvers.NoReverseMatch` exception is raised
from a method when rendering a template, it is not silenced. For example,
``{{ obj.view_href }}`` will cause template rendering to fail if
``view_href()`` raises ``NoReverseMatch``. There is no change to the
:ttag:`{% url %}<url>` tag, it causes template rendering to fail like always
when ``NoReverseMatch`` is raised.
* If a ``NoReverseMatch`` exception is raised from a method when rendering a
template, it is not silenced. For example, ``{{ obj.view_href }}`` will
cause template rendering to fail if ``view_href()`` raises
``NoReverseMatch``. There is no change to the :ttag:`{% url %}<url>` tag, it
causes template rendering to fail like always when ``NoReverseMatch`` is
raised.
* :meth:`django.test.Client.logout` now calls
:meth:`django.contrib.auth.logout` which will send the

View File

@ -82,8 +82,7 @@ Bugfixes
(:ticket:`23815`).
* Fixed a crash in the ``django.contrib.auth.redirect_to_login`` view when
passing a :func:`~django.core.urlresolvers.reverse_lazy` result on Python 3
(:ticket:`24097`).
passing a ``reverse_lazy()`` result on Python 3 (:ticket:`24097`).
* Added correct formats for Greek (``el``) (:ticket:`23967`).

View File

@ -1112,9 +1112,8 @@ Miscellaneous
* The default max size of the Oracle test tablespace has increased from 300M
(or 200M, before 1.7.2) to 500M.
* :func:`~django.core.urlresolvers.reverse` and
:func:`~django.core.urlresolvers.reverse_lazy` now return Unicode strings
instead of byte strings.
* ``reverse()`` and ``reverse_lazy()`` now return Unicode strings instead of
byte strings.
* The ``CacheClass`` shim has been removed from all cache backends.
These aliases were provided for backwards compatibility with Django 1.3.
@ -1334,8 +1333,8 @@ Using an incorrect count of unpacked values in the :ttag:`for` template tag
Using an incorrect count of unpacked values in :ttag:`for` tag will raise an
exception rather than fail silently in Django 1.10.
Passing a dotted path to :func:`~django.core.urlresolvers.reverse()` and :ttag:`url`
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Passing a dotted path to ``reverse()`` and :ttag:`url`
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Reversing URLs by Python path is an expensive operation as it causes the
path being reversed to be imported. This behavior has also resulted in a

View File

@ -1083,12 +1083,10 @@ Miscellaneous
:attr:`~django.test.SimpleTestCase.allow_database_queries` class attribute
to ``True`` on your test class.
* :attr:`ResolverMatch.app_name
<django.core.urlresolvers.ResolverMatch.app_name>` was changed to contain
the full namespace path in the case of nested namespaces. For consistency
with :attr:`ResolverMatch.namespace
<django.core.urlresolvers.ResolverMatch.namespace>`, the empty value is now
an empty string instead of ``None``.
* ``ResolverMatch.app_name`` was changed to contain the full namespace path in
the case of nested namespaces. For consistency with
``ResolverMatch.namespace``, the empty value is now an empty string instead
of ``None``.
* For security hardening, session keys must be at least 8 characters.

View File

@ -98,7 +98,7 @@ First we need to add :meth:`~django.db.models.Model.get_absolute_url()` to our
.. snippet::
:filename: models.py
from django.core.urlresolvers import reverse
from django.urls import reverse
from django.db import models
class Author(models.Model):
@ -115,7 +115,7 @@ here; we don't have to write any logic ourselves:
:filename: views.py
from django.views.generic.edit import CreateView, UpdateView, DeleteView
from django.core.urlresolvers import reverse_lazy
from django.urls import reverse_lazy
from myapp.models import Author
class AuthorCreate(CreateView):
@ -131,8 +131,8 @@ here; we don't have to write any logic ourselves:
success_url = reverse_lazy('author-list')
.. note::
We have to use :func:`~django.core.urlresolvers.reverse_lazy` here, not
just ``reverse`` as the urls are not loaded when the file is imported.
We have to use :func:`~django.urls.reverse_lazy` here, not just
``reverse()`` as the urls are not loaded when the file is imported.
The ``fields`` attribute works the same way as the ``fields`` attribute on the
inner ``Meta`` class on :class:`~django.forms.ModelForm`. Unless you define the

View File

@ -225,7 +225,7 @@ We'll demonstrate this with the ``Author`` model we used in the
:filename: views.py
from django.http import HttpResponseForbidden, HttpResponseRedirect
from django.core.urlresolvers import reverse
from django.urls import reverse
from django.views.generic import View
from django.views.generic.detail import SingleObjectMixin
from books.models import Author
@ -445,7 +445,7 @@ Our new ``AuthorDetail`` looks like this::
from django import forms
from django.http import HttpResponseForbidden
from django.core.urlresolvers import reverse
from django.urls import reverse
from django.views.generic import DetailView
from django.views.generic.edit import FormMixin
from books.models import Author
@ -541,7 +541,7 @@ can find the author we're talking about, and we have to remember to set
``template_name`` to ensure that form errors will render the same
template as ``AuthorDisplay`` is using on ``GET``::
from django.core.urlresolvers import reverse
from django.urls import reverse
from django.http import HttpResponseForbidden
from django.views.generic import FormView
from django.views.generic.detail import SingleObjectMixin

View File

@ -103,9 +103,8 @@ This example is equivalent to::
* A model: the model's :meth:`~django.db.models.Model.get_absolute_url()`
function will be called.
* A view name, possibly with arguments: :func:`urlresolvers.reverse
<django.core.urlresolvers.reverse>` will be used to reverse-resolve the
name.
* A view name, possibly with arguments: :func:`~django.urls.reverse` will be
used to reverse-resolve the name.
* An absolute or relative URL, which will be used as-is for the redirect
location.
@ -131,7 +130,7 @@ You can use the :func:`redirect` function in a number of ways.
2. By passing the name of a view and optionally some positional or
keyword arguments; the URL will be reverse resolved using the
:func:`~django.core.urlresolvers.reverse` method::
:func:`~django.urls.reverse` method::
def my_view(request):
...

View File

@ -533,8 +533,7 @@ layers where URLs are needed:
* In templates: Using the :ttag:`url` template tag.
* In Python code: Using the :func:`django.core.urlresolvers.reverse`
function.
* In Python code: Using the :func:`~django.urls.reverse` function.
* In higher level code related to handling of URLs of Django model instances:
The :meth:`~django.db.models.Model.get_absolute_url` method.
@ -571,7 +570,7 @@ You can obtain these in template code by using:
Or in Python code::
from django.core.urlresolvers import reverse
from django.urls import reverse
from django.http import HttpResponseRedirect
def redirect_to_year(request):
@ -671,8 +670,8 @@ the fully qualified name into parts and then tries the following lookup:
2. If there is a current application defined, Django finds and returns the URL
resolver for that instance. The current application can be specified with
the ``current_app`` argument to the
:func:`~django.core.urlresolvers.reverse()` function.
the ``current_app`` argument to the :func:`~django.urls.reverse()`
function.
The :ttag:`url` template tag uses the namespace of the currently resolved
view as the current application in a

View File

@ -1360,7 +1360,7 @@ After defining these URL patterns, Django will automatically add the
language prefix to the URL patterns that were added by the ``i18n_patterns``
function. Example::
from django.core.urlresolvers import reverse
from django.urls import reverse
from django.utils.translation import activate
>>> activate('en')
@ -1414,11 +1414,10 @@ URL patterns can also be marked translatable using the
url(_(r'^news/'), include(news_patterns, namespace='news')),
)
After you've created the translations, the
:func:`~django.core.urlresolvers.reverse` function will return the URL in the
active language. Example::
After you've created the translations, the :func:`~django.urls.reverse`
function will return the URL in the active language. Example::
from django.core.urlresolvers import reverse
from django.urls import reverse
from django.utils.translation import activate
>>> activate('en')

View File

@ -411,7 +411,7 @@ For example, you can create ``myproject/jinja2.py`` with this content::
from __future__ import absolute_import # Python 2 only
from django.contrib.staticfiles.storage import staticfiles_storage
from django.core.urlresolvers import reverse
from django.urls import reverse
from jinja2 import Environment

View File

@ -507,9 +507,8 @@ Specifically, a ``Response`` object has the following attributes:
.. attribute:: resolver_match
An instance of :class:`~django.core.urlresolvers.ResolverMatch` for the
response. You can use the
:attr:`~django.core.urlresolvers.ResolverMatch.func` attribute, for
An instance of :class:`~django.urls.ResolverMatch` for the response.
You can use the :attr:`~django.urls.ResolverMatch.func` attribute, for
example, to verify the view that served the response::
# my_view here is a function based view
@ -520,7 +519,7 @@ Specifically, a ``Response`` object has the following attributes:
self.assertEqual(response.resolver_match.func.__name__, MyView.as_view().__name__)
If the given URL is not found, accessing this attribute will raise a
:exc:`~django.core.urlresolvers.Resolver404` exception.
:exc:`~django.urls.Resolver404` exception.
You can also use dictionary syntax on the response object to query the value
of any settings in the HTTP headers. For example, you could determine the

View File

@ -10,10 +10,10 @@ from django.contrib.admin.tests import AdminSeleniumWebDriverTestCase
from django.contrib.admin.views.main import ALL_VAR, SEARCH_VAR, ChangeList
from django.contrib.auth.models import User
from django.contrib.contenttypes.models import ContentType
from django.core.urlresolvers import reverse
from django.template import Context, Template
from django.test import TestCase, ignore_warnings, override_settings
from django.test.client import RequestFactory
from django.urls import reverse
from django.utils import formats, six
from django.utils.deprecation import RemovedInDjango20Warning

View File

@ -1,9 +1,9 @@
from functools import update_wrapper
from django.contrib import admin
from django.core.urlresolvers import reverse
from django.db import models
from django.http import HttpResponseRedirect
from django.urls import reverse
from django.utils.encoding import python_2_unicode_compatible

View File

@ -4,9 +4,9 @@ import datetime
from django.contrib.admin.utils import quote
from django.contrib.auth.models import User
from django.core.urlresolvers import reverse
from django.template.response import TemplateResponse
from django.test import TestCase, override_settings
from django.urls import reverse
from .models import Action, Car, Person

View File

@ -7,9 +7,9 @@ from django.contrib.admindocs import utils
from django.contrib.admindocs.views import get_return_data_type
from django.contrib.auth.models import User
from django.contrib.sites.models import Site
from django.core.urlresolvers import reverse
from django.test import TestCase, modify_settings, override_settings
from django.test.utils import captured_stderr
from django.urls import reverse
from .models import Company, Person

View File

@ -7,8 +7,8 @@ from django.contrib.admin.helpers import InlineAdminForm
from django.contrib.admin.tests import AdminSeleniumWebDriverTestCase
from django.contrib.auth.models import Permission, User
from django.contrib.contenttypes.models import ContentType
from django.core.urlresolvers import reverse
from django.test import RequestFactory, TestCase, override_settings
from django.urls import reverse
from .admin import InnerInline, site as admin_site
from .models import (

View File

@ -6,8 +6,8 @@ from django.contrib.admin.models import ADDITION, CHANGE, DELETION, LogEntry
from django.contrib.admin.utils import quote
from django.contrib.auth.models import User
from django.contrib.contenttypes.models import ContentType
from django.core.urlresolvers import reverse
from django.test import TestCase, override_settings
from django.urls import reverse
from django.utils import six
from django.utils.encoding import force_bytes
from django.utils.html import escape

View File

@ -5,9 +5,9 @@ import datetime
from django.conf.urls import url
from django.contrib import admin
from django.contrib.auth.models import User
from django.core.urlresolvers import reverse
from django.test import TestCase, override_settings
from django.test.client import RequestFactory
from django.urls import reverse
from .models import Article

View File

@ -23,7 +23,6 @@ from django.contrib.staticfiles.storage import staticfiles_storage
from django.core import mail
from django.core.checks import Error
from django.core.files import temp as tempfile
from django.core.urlresolvers import NoReverseMatch, resolve, reverse
from django.forms.utils import ErrorList
from django.template.loader import render_to_string
from django.template.response import TemplateResponse
@ -32,6 +31,7 @@ from django.test import (
override_settings, skipUnlessDBFeature,
)
from django.test.utils import override_script_prefix, patch_logger
from django.urls import NoReverseMatch, resolve, reverse
from django.utils import formats, six, translation
from django.utils._os import upath
from django.utils.cache import get_max_age

View File

@ -15,9 +15,9 @@ from django.contrib.admin.tests import AdminSeleniumWebDriverTestCase
from django.contrib.auth.models import User
from django.core.files.storage import default_storage
from django.core.files.uploadedfile import SimpleUploadedFile
from django.core.urlresolvers import reverse
from django.db.models import CharField, DateField
from django.test import SimpleTestCase, TestCase, override_settings
from django.urls import reverse
from django.utils import six, translation
from . import models

View File

@ -20,12 +20,12 @@ from django.contrib.auth.views import login as login_view, redirect_to_login
from django.contrib.sessions.middleware import SessionMiddleware
from django.contrib.sites.requests import RequestSite
from django.core import mail
from django.core.urlresolvers import NoReverseMatch, reverse, reverse_lazy
from django.db import connection
from django.http import HttpRequest, QueryDict
from django.middleware.csrf import CsrfViewMiddleware, get_token
from django.test import TestCase, override_settings
from django.test.utils import patch_logger
from django.urls import NoReverseMatch, reverse, reverse_lazy
from django.utils.encoding import force_text
from django.utils.http import urlquote
from django.utils.six.moves.urllib.parse import ParseResult, urlparse

View File

@ -2,7 +2,6 @@
from __future__ import unicode_literals
from django.contrib.admin.tests import AdminSeleniumWebDriverTestCase
from django.core.urlresolvers import reverse
from django.forms import (
CheckboxSelectMultiple, ClearableFileInput, RadioSelect, TextInput,
)
@ -10,6 +9,7 @@ from django.forms.widgets import (
ChoiceFieldRenderer, ChoiceInput, RadioFieldRenderer,
)
from django.test import SimpleTestCase, override_settings
from django.urls import reverse
from django.utils import six
from django.utils.encoding import force_text, python_2_unicode_compatible
from django.utils.safestring import SafeData

View File

@ -9,12 +9,12 @@ from django.contrib.auth.models import User
from django.contrib.contenttypes.admin import GenericTabularInline
from django.contrib.contenttypes.forms import generic_inlineformset_factory
from django.contrib.contenttypes.models import ContentType
from django.core.urlresolvers import reverse
from django.forms.formsets import DEFAULT_MAX_NUM
from django.forms.models import ModelForm
from django.test import (
RequestFactory, SimpleTestCase, TestCase, override_settings,
)
from django.urls import reverse
from .admin import MediaInline, MediaPermanentInline, site as admin_site
from .models import Category, Episode, EpisodePermanent, Media, PhoneNumber

View File

@ -1,7 +1,7 @@
from django.core.urlresolvers import reverse
from django.db import models
from django.db.models import QuerySet
from django.db.models.manager import BaseManager
from django.urls import reverse
from django.utils.encoding import python_2_unicode_compatible

View File

@ -4,10 +4,10 @@ import time
import unittest
from django.core.exceptions import ImproperlyConfigured
from django.core.urlresolvers import resolve
from django.http import HttpResponse
from django.test import RequestFactory, SimpleTestCase, override_settings
from django.test.utils import require_jinja2
from django.urls import resolve
from django.views.generic import RedirectView, TemplateView, View
from . import views

View File

@ -2,9 +2,9 @@ from __future__ import unicode_literals
from django import forms
from django.core.exceptions import ImproperlyConfigured
from django.core.urlresolvers import reverse
from django.test import SimpleTestCase, TestCase, override_settings
from django.test.client import RequestFactory
from django.urls import reverse
from django.views.generic.base import View
from django.views.generic.edit import CreateView, FormMixin, ModelFormMixin

View File

@ -2,7 +2,7 @@ from __future__ import unicode_literals
from django.contrib.auth.decorators import login_required
from django.core.paginator import Paginator
from django.core.urlresolvers import reverse, reverse_lazy
from django.urls import reverse, reverse_lazy
from django.utils.decorators import method_decorator
from django.views import generic

View File

@ -3,12 +3,12 @@ from __future__ import unicode_literals
import os
from django.core.exceptions import ImproperlyConfigured
from django.core.urlresolvers import clear_url_caches, reverse, translate_url
from django.http import HttpResponsePermanentRedirect
from django.middleware.locale import LocaleMiddleware
from django.template import Context, Template
from django.test import SimpleTestCase, override_settings
from django.test.utils import override_script_prefix
from django.urls import clear_url_caches, reverse, translate_url
from django.utils import translation
from django.utils._os import upath

View File

@ -4,8 +4,8 @@ from django.contrib.messages.api import MessageFailure
from django.contrib.messages.constants import DEFAULT_LEVELS
from django.contrib.messages.storage import base, default_storage
from django.contrib.messages.storage.base import Message
from django.core.urlresolvers import reverse
from django.test import modify_settings, override_settings
from django.urls import reverse
from django.utils.translation import ugettext_lazy

View File

@ -1,5 +1,5 @@
from django.core.urlresolvers import reverse
from django.test import SimpleTestCase, override_settings
from django.urls import reverse
from .urls import ContactFormViewWithMsg

View File

@ -2,10 +2,10 @@ from django import forms
from django.conf.urls import url
from django.contrib import messages
from django.contrib.messages.views import SuccessMessageMixin
from django.core.urlresolvers import reverse
from django.http import HttpResponse, HttpResponseRedirect
from django.template import engines
from django.template.response import TemplateResponse
from django.urls import reverse
from django.views.decorators.cache import never_cache
from django.views.generic.edit import FormView

Some files were not shown because too many files have changed in this diff Show More