Fixed #24127 -- Changed the default current_app to the current namespace.
Changed the url template tag to use request.resolver_match.namespace as a default for the current_app argument if request.current_app is not set.
This commit is contained in:
parent
6024fd5dc2
commit
bc7923beff
|
@ -152,6 +152,10 @@ class Context(BaseContext):
|
||||||
def current_app(self):
|
def current_app(self):
|
||||||
return None if self._current_app is _current_app_undefined else self._current_app
|
return None if self._current_app is _current_app_undefined else self._current_app
|
||||||
|
|
||||||
|
@property
|
||||||
|
def is_current_app_set(self):
|
||||||
|
return self._current_app is not _current_app_undefined
|
||||||
|
|
||||||
@contextmanager
|
@contextmanager
|
||||||
def bind_template(self, template):
|
def bind_template(self, template):
|
||||||
if self.template is not None:
|
if self.template is not None:
|
||||||
|
|
|
@ -479,9 +479,16 @@ class URLNode(Node):
|
||||||
try:
|
try:
|
||||||
current_app = context.request.current_app
|
current_app = context.request.current_app
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
# Change the fallback value to None when the deprecation path for
|
# Leave only the else block when the deprecation path for
|
||||||
# Context.current_app completes in Django 1.10.
|
# Context.current_app completes in Django 1.10.
|
||||||
current_app = context.current_app
|
# Can also remove the Context.is_current_app_set property.
|
||||||
|
if context.is_current_app_set:
|
||||||
|
current_app = context.current_app
|
||||||
|
else:
|
||||||
|
try:
|
||||||
|
current_app = context.request.resolver_match.namespace
|
||||||
|
except AttributeError:
|
||||||
|
current_app = None
|
||||||
|
|
||||||
# Try to look up the URL twice: once given the view name, and again
|
# Try to look up the URL twice: once given the view name, and again
|
||||||
# relative to what we guess is the "main" app. If they both fail,
|
# relative to what we guess is the "main" app. If they both fail,
|
||||||
|
|
|
@ -895,6 +895,12 @@ Miscellaneous
|
||||||
whitespace by default. This can be disabled by setting the new
|
whitespace by default. This can be disabled by setting the new
|
||||||
:attr:`~django.forms.CharField.strip` argument to ``False``.
|
:attr:`~django.forms.CharField.strip` argument to ``False``.
|
||||||
|
|
||||||
|
* If neither :attr:`request.current_app <django.http.HttpRequest.current_app>`
|
||||||
|
nor :class:`Context.current_app <django.template.Context>` are set, the
|
||||||
|
:ttag:`url` template tag will now use the namespace of the current request.
|
||||||
|
Set ``request.current_app`` to ``None`` if you don't want to use a namespace
|
||||||
|
hint.
|
||||||
|
|
||||||
.. _deprecated-features-1.9:
|
.. _deprecated-features-1.9:
|
||||||
|
|
||||||
Features deprecated in 1.9
|
Features deprecated in 1.9
|
||||||
|
|
|
@ -669,11 +669,16 @@ the fully qualified name into parts and then tries the following lookup:
|
||||||
example, ``'polls'``). This will yield a list of instances of that
|
example, ``'polls'``). This will yield a list of instances of that
|
||||||
application.
|
application.
|
||||||
|
|
||||||
2. If there is a *current* application defined, Django finds and returns
|
2. If there is a current application defined, Django finds and returns the URL
|
||||||
the URL resolver for that instance. The *current* application can be
|
resolver for that instance. The current application can be specified with
|
||||||
specified as an attribute on the request. Applications that expect to
|
the ``current_app`` argument to the
|
||||||
have multiple deployments should set the ``current_app`` attribute on
|
:func:`~django.core.urlresolvers.reverse()` function.
|
||||||
the ``request`` being processed.
|
|
||||||
|
The :ttag:`url` template tag uses the namespace of the currently resolved
|
||||||
|
view as the current application in a
|
||||||
|
:class:`~django.template.RequestContext`. You can override this default by
|
||||||
|
setting the current application on the :attr:`request.current_app
|
||||||
|
<django.http.HttpRequest.current_app>` attribute.
|
||||||
|
|
||||||
.. versionchanged:: 1.8
|
.. versionchanged:: 1.8
|
||||||
|
|
||||||
|
@ -682,8 +687,11 @@ the fully qualified name into parts and then tries the following lookup:
|
||||||
:class:`~django.template.RequestContext` that is used to render a
|
:class:`~django.template.RequestContext` that is used to render a
|
||||||
template.
|
template.
|
||||||
|
|
||||||
The current application can also be specified manually as an argument
|
.. versionchanged:: 1.9
|
||||||
to the :func:`~django.core.urlresolvers.reverse` function.
|
|
||||||
|
Previously, the :ttag:`url` template tag did not use the namespace of the
|
||||||
|
currently resolved view and you had to set the ``current_app`` attribute
|
||||||
|
on the request.
|
||||||
|
|
||||||
3. If there is no current application. Django looks for a default
|
3. If there is no current application. Django looks for a default
|
||||||
application instance. The default application instance is the instance
|
application instance. The default application instance is the instance
|
||||||
|
@ -751,13 +759,6 @@ Using this setup, the following lookups are possible:
|
||||||
|
|
||||||
{% url 'polls:index' %}
|
{% url 'polls:index' %}
|
||||||
|
|
||||||
Note that reversing in the template requires the ``current_app`` be added as
|
|
||||||
an attribute to the ``request`` like this::
|
|
||||||
|
|
||||||
def render_to_response(self, context, **response_kwargs):
|
|
||||||
self.request.current_app = self.request.resolver_match.namespace
|
|
||||||
return super(DetailView, self).render_to_response(context, **response_kwargs)
|
|
||||||
|
|
||||||
* If there is no current instance - say, if we were rendering a page
|
* If there is no current instance - say, if we were rendering a page
|
||||||
somewhere else on the site - ``'polls:index'`` will resolve to the last
|
somewhere else on the site - ``'polls:index'`` will resolve to the last
|
||||||
registered instance of ``polls``. Since there is no default instance
|
registered instance of ``polls``. Since there is no default instance
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
# coding: utf-8
|
# coding: utf-8
|
||||||
from django.core.urlresolvers import NoReverseMatch
|
from django.core.urlresolvers import NoReverseMatch, resolve
|
||||||
from django.template import TemplateSyntaxError
|
from django.template import RequestContext, TemplateSyntaxError
|
||||||
from django.test import SimpleTestCase, ignore_warnings, override_settings
|
from django.test import (
|
||||||
|
RequestFactory, SimpleTestCase, ignore_warnings, override_settings,
|
||||||
|
)
|
||||||
from django.utils.deprecation import RemovedInDjango110Warning
|
from django.utils.deprecation import RemovedInDjango110Warning
|
||||||
|
|
||||||
from ..utils import setup
|
from ..utils import setup
|
||||||
|
@ -252,3 +254,29 @@ class UrlTagTests(SimpleTestCase):
|
||||||
def test_url_asvar03(self):
|
def test_url_asvar03(self):
|
||||||
output = self.engine.render_to_string('url-asvar03')
|
output = self.engine.render_to_string('url-asvar03')
|
||||||
self.assertEqual(output, '')
|
self.assertEqual(output, '')
|
||||||
|
|
||||||
|
@setup({'url-namespace01': '{% url "app:named.client" 42 %}'})
|
||||||
|
def test_url_namespace01(self):
|
||||||
|
request = RequestFactory().get('/')
|
||||||
|
request.resolver_match = resolve('/ns1/')
|
||||||
|
template = self.engine.get_template('url-namespace01')
|
||||||
|
context = RequestContext(request)
|
||||||
|
output = template.render(context)
|
||||||
|
self.assertEqual(output, '/ns1/named-client/42/')
|
||||||
|
|
||||||
|
@setup({'url-namespace02': '{% url "app:named.client" 42 %}'})
|
||||||
|
def test_url_namespace02(self):
|
||||||
|
request = RequestFactory().get('/')
|
||||||
|
request.resolver_match = resolve('/ns2/')
|
||||||
|
template = self.engine.get_template('url-namespace02')
|
||||||
|
context = RequestContext(request)
|
||||||
|
output = template.render(context)
|
||||||
|
self.assertEqual(output, '/ns2/named-client/42/')
|
||||||
|
|
||||||
|
@setup({'url-namespace03': '{% url "app:named.client" 42 %}'})
|
||||||
|
def test_url_namespace03(self):
|
||||||
|
request = RequestFactory().get('/')
|
||||||
|
template = self.engine.get_template('url-namespace03')
|
||||||
|
context = RequestContext(request)
|
||||||
|
output = template.render(context)
|
||||||
|
self.assertEqual(output, '/ns2/named-client/42/')
|
||||||
|
|
|
@ -1,19 +1,26 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
from django.conf.urls import url
|
from django.conf.urls import include, url
|
||||||
|
|
||||||
from . import views
|
from . import views
|
||||||
|
|
||||||
urlpatterns = [
|
ns_patterns = [
|
||||||
# Test urls for testing reverse lookups
|
# Test urls for testing reverse lookups
|
||||||
url(r'^$', views.index),
|
url(r'^$', views.index),
|
||||||
url(r'^client/([0-9,]+)/$', views.client),
|
url(r'^client/([0-9,]+)/$', views.client),
|
||||||
url(r'^client/(?P<id>[0-9]+)/(?P<action>[^/]+)/$', views.client_action),
|
url(r'^client/(?P<id>[0-9]+)/(?P<action>[^/]+)/$', views.client_action),
|
||||||
url(r'^client/(?P<client_id>[0-9]+)/(?P<action>[^/]+)/$', views.client_action),
|
url(r'^client/(?P<client_id>[0-9]+)/(?P<action>[^/]+)/$', views.client_action),
|
||||||
url(r'^named-client/([0-9]+)/$', views.client2, name="named.client"),
|
url(r'^named-client/([0-9]+)/$', views.client2, name="named.client"),
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
urlpatterns = ns_patterns + [
|
||||||
# Unicode strings are permitted everywhere.
|
# Unicode strings are permitted everywhere.
|
||||||
url(r'^Юникод/(\w+)/$', views.client2, name="метка_оператора"),
|
url(r'^Юникод/(\w+)/$', views.client2, name="метка_оператора"),
|
||||||
url(r'^Юникод/(?P<tag>\S+)/$', views.client2, name="метка_оператора_2"),
|
url(r'^Юникод/(?P<tag>\S+)/$', views.client2, name="метка_оператора_2"),
|
||||||
|
|
||||||
|
# Test urls for namespaces and current_app
|
||||||
|
url(r'ns1/', include((ns_patterns, 'app'), 'ns1')),
|
||||||
|
url(r'ns2/', include((ns_patterns, 'app'))),
|
||||||
]
|
]
|
||||||
|
|
Loading…
Reference in New Issue