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.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.version import get_docs_version
|
||||
|
||||
|
@ -95,14 +95,14 @@ CSRF_FAILURE_TEMPLATE = """
|
|||
</body>
|
||||
</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
|
||||
"""
|
||||
from django.middleware.csrf import REASON_NO_REFERER, REASON_NO_CSRF_COOKIE
|
||||
t = Engine().from_string(CSRF_FAILURE_TEMPLATE)
|
||||
c = Context({
|
||||
'title': _("Forbidden"),
|
||||
'main': _("CSRF verification failed. Request aborted."),
|
||||
|
@ -131,4 +131,13 @@ def csrf_failure(request, reason=""):
|
|||
'docs_version': get_docs_version(),
|
||||
'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')
|
||||
|
|
|
@ -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
|
||||
: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
|
||||
|
||||
CSRF_HEADER_NAME
|
||||
|
|
|
@ -114,7 +114,9 @@ Cache
|
|||
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
|
||||
^^^^^^^^^^^^^^^^^
|
||||
|
|
|
@ -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.views.csrf import CSRF_FAILURE_TEMPLATE_NAME, csrf_failure
|
||||
|
||||
|
||||
@override_settings(ROOT_URLCONF="view_tests.urls")
|
||||
|
@ -70,3 +74,29 @@ class CsrfViewTests(SimpleTestCase):
|
|||
"""
|
||||
response = self.client.post('/')
|
||||
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