Fixed #25695 -- Added template_name parameter to csrf_failure() view.
This commit is contained in:
parent
20d2778597
commit
16945f0e9c
|
@ -1,6 +1,6 @@
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.http import HttpResponseForbidden
|
from django.http import HttpResponseForbidden
|
||||||
from django.template import Context, Engine
|
from django.template import Context, Engine, TemplateDoesNotExist, loader
|
||||||
from django.utils.translation import ugettext as _
|
from django.utils.translation import ugettext as _
|
||||||
from django.utils.version import get_docs_version
|
from django.utils.version import get_docs_version
|
||||||
|
|
||||||
|
@ -95,14 +95,14 @@ CSRF_FAILURE_TEMPLATE = """
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
"""
|
"""
|
||||||
|
CSRF_FAILURE_TEMPLATE_NAME = "403_csrf.html"
|
||||||
|
|
||||||
|
|
||||||
def csrf_failure(request, reason=""):
|
def csrf_failure(request, reason="", template_name=CSRF_FAILURE_TEMPLATE_NAME):
|
||||||
"""
|
"""
|
||||||
Default view used when request fails CSRF protection
|
Default view used when request fails CSRF protection
|
||||||
"""
|
"""
|
||||||
from django.middleware.csrf import REASON_NO_REFERER, REASON_NO_CSRF_COOKIE
|
from django.middleware.csrf import REASON_NO_REFERER, REASON_NO_CSRF_COOKIE
|
||||||
t = Engine().from_string(CSRF_FAILURE_TEMPLATE)
|
|
||||||
c = Context({
|
c = Context({
|
||||||
'title': _("Forbidden"),
|
'title': _("Forbidden"),
|
||||||
'main': _("CSRF verification failed. Request aborted."),
|
'main': _("CSRF verification failed. Request aborted."),
|
||||||
|
@ -131,4 +131,13 @@ def csrf_failure(request, reason=""):
|
||||||
'docs_version': get_docs_version(),
|
'docs_version': get_docs_version(),
|
||||||
'more': _("More information is available with DEBUG=True."),
|
'more': _("More information is available with DEBUG=True."),
|
||||||
})
|
})
|
||||||
|
try:
|
||||||
|
t = loader.get_template(template_name)
|
||||||
|
except TemplateDoesNotExist:
|
||||||
|
if template_name == CSRF_FAILURE_TEMPLATE_NAME:
|
||||||
|
# If the default template doesn't exist, use the string template.
|
||||||
|
t = Engine().from_string(CSRF_FAILURE_TEMPLATE)
|
||||||
|
else:
|
||||||
|
# Raise if a developer-specified template doesn't exist.
|
||||||
|
raise
|
||||||
return HttpResponseForbidden(t.render(c), content_type='text/html')
|
return HttpResponseForbidden(t.render(c), content_type='text/html')
|
||||||
|
|
|
@ -385,6 +385,15 @@ where ``reason`` is a short message (intended for developers or logging, not for
|
||||||
end users) indicating the reason the request was rejected. See
|
end users) indicating the reason the request was rejected. See
|
||||||
:doc:`/ref/csrf`.
|
:doc:`/ref/csrf`.
|
||||||
|
|
||||||
|
``django.views.csrf.csrf_failure()`` accepts an additional ``template_name``
|
||||||
|
parameter that defaults to ``'403_csrf.html'``. If a template with that name
|
||||||
|
exists, it will be used to render the page.
|
||||||
|
|
||||||
|
.. versionchanged:: 1.10
|
||||||
|
|
||||||
|
The ``template_name`` parameter and the behavior of searching for a template
|
||||||
|
called ``403_csrf.html`` were added to ``csrf_failure()``.
|
||||||
|
|
||||||
.. setting:: CSRF_HEADER_NAME
|
.. setting:: CSRF_HEADER_NAME
|
||||||
|
|
||||||
CSRF_HEADER_NAME
|
CSRF_HEADER_NAME
|
||||||
|
|
|
@ -114,7 +114,9 @@ Cache
|
||||||
CSRF
|
CSRF
|
||||||
^^^^
|
^^^^
|
||||||
|
|
||||||
* ...
|
* The default :setting:`CSRF_FAILURE_VIEW`, ``views.csrf.csrf_failure()`` now
|
||||||
|
accepts an optional ``template_name`` parameter, defaulting to
|
||||||
|
``'403_csrf.html'``, to control the template used to render the page.
|
||||||
|
|
||||||
Database backends
|
Database backends
|
||||||
^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
@ -1,5 +1,9 @@
|
||||||
from django.test import Client, SimpleTestCase, override_settings
|
from django.template import TemplateDoesNotExist
|
||||||
|
from django.test import (
|
||||||
|
Client, RequestFactory, SimpleTestCase, override_settings,
|
||||||
|
)
|
||||||
from django.utils.translation import override
|
from django.utils.translation import override
|
||||||
|
from django.views.csrf import CSRF_FAILURE_TEMPLATE_NAME, csrf_failure
|
||||||
|
|
||||||
|
|
||||||
@override_settings(ROOT_URLCONF="view_tests.urls")
|
@override_settings(ROOT_URLCONF="view_tests.urls")
|
||||||
|
@ -70,3 +74,29 @@ class CsrfViewTests(SimpleTestCase):
|
||||||
"""
|
"""
|
||||||
response = self.client.post('/')
|
response = self.client.post('/')
|
||||||
self.assertContains(response, "Forbidden", status_code=403)
|
self.assertContains(response, "Forbidden", status_code=403)
|
||||||
|
|
||||||
|
@override_settings(TEMPLATES=[{
|
||||||
|
'BACKEND': 'django.template.backends.django.DjangoTemplates',
|
||||||
|
'OPTIONS': {
|
||||||
|
'loaders': [
|
||||||
|
('django.template.loaders.locmem.Loader', {
|
||||||
|
CSRF_FAILURE_TEMPLATE_NAME: 'Test template for CSRF failure'
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
},
|
||||||
|
}])
|
||||||
|
def test_custom_template(self):
|
||||||
|
"""
|
||||||
|
A custom CSRF_FAILURE_TEMPLATE_NAME is used.
|
||||||
|
"""
|
||||||
|
response = self.client.post('/')
|
||||||
|
self.assertContains(response, "Test template for CSRF failure", status_code=403)
|
||||||
|
|
||||||
|
def test_custom_template_does_not_exist(self):
|
||||||
|
"""
|
||||||
|
An exception is raised if a nonexistent template is supplied.
|
||||||
|
"""
|
||||||
|
factory = RequestFactory()
|
||||||
|
request = factory.post('/')
|
||||||
|
with self.assertRaises(TemplateDoesNotExist):
|
||||||
|
csrf_failure(request, template_name="nonexistent.html")
|
||||||
|
|
Loading…
Reference in New Issue