Fixed #25469 -- Added autoescape option to DjangoTemplates backend.
Thanks Aymeric for the initial patch and Carl for review.
This commit is contained in:
parent
a8f05f405f
commit
19a5f6da32
|
@ -23,6 +23,7 @@ class DjangoTemplates(BaseEngine):
|
||||||
def __init__(self, params):
|
def __init__(self, params):
|
||||||
params = params.copy()
|
params = params.copy()
|
||||||
options = params.pop('OPTIONS').copy()
|
options = params.pop('OPTIONS').copy()
|
||||||
|
options.setdefault('autoescape', True)
|
||||||
options.setdefault('debug', settings.DEBUG)
|
options.setdefault('debug', settings.DEBUG)
|
||||||
options.setdefault('file_charset', settings.FILE_CHARSET)
|
options.setdefault('file_charset', settings.FILE_CHARSET)
|
||||||
libraries = options.get('libraries', {})
|
libraries = options.get('libraries', {})
|
||||||
|
@ -60,7 +61,7 @@ class Template(object):
|
||||||
return self.template.origin
|
return self.template.origin
|
||||||
|
|
||||||
def render(self, context=None, request=None):
|
def render(self, context=None, request=None):
|
||||||
context = make_context(context, request)
|
context = make_context(context, request, autoescape=self.backend.engine.autoescape)
|
||||||
try:
|
try:
|
||||||
return self.template.render(context)
|
return self.template.render(context)
|
||||||
except TemplateDoesNotExist as exc:
|
except TemplateDoesNotExist as exc:
|
||||||
|
|
|
@ -201,9 +201,9 @@ class RequestContext(Context):
|
||||||
Additional processors can be specified as a list of callables
|
Additional processors can be specified as a list of callables
|
||||||
using the "processors" keyword argument.
|
using the "processors" keyword argument.
|
||||||
"""
|
"""
|
||||||
def __init__(self, request, dict_=None, processors=None, use_l10n=None, use_tz=None):
|
def __init__(self, request, dict_=None, processors=None, use_l10n=None, use_tz=None, autoescape=True):
|
||||||
super(RequestContext, self).__init__(
|
super(RequestContext, self).__init__(
|
||||||
dict_, use_l10n=use_l10n, use_tz=use_tz)
|
dict_, use_l10n=use_l10n, use_tz=use_tz, autoescape=autoescape)
|
||||||
self.request = request
|
self.request = request
|
||||||
self._processors = () if processors is None else tuple(processors)
|
self._processors = () if processors is None else tuple(processors)
|
||||||
self._processors_index = len(self.dicts)
|
self._processors_index = len(self.dicts)
|
||||||
|
@ -245,17 +245,17 @@ class RequestContext(Context):
|
||||||
return new_context
|
return new_context
|
||||||
|
|
||||||
|
|
||||||
def make_context(context, request=None):
|
def make_context(context, request=None, **kwargs):
|
||||||
"""
|
"""
|
||||||
Create a suitable Context from a plain dict and optionally an HttpRequest.
|
Create a suitable Context from a plain dict and optionally an HttpRequest.
|
||||||
"""
|
"""
|
||||||
if request is None:
|
if request is None:
|
||||||
context = Context(context)
|
context = Context(context, **kwargs)
|
||||||
else:
|
else:
|
||||||
# The following pattern is required to ensure values from
|
# The following pattern is required to ensure values from
|
||||||
# context override those from template context processors.
|
# context override those from template context processors.
|
||||||
original_context = context
|
original_context = context
|
||||||
context = RequestContext(request)
|
context = RequestContext(request, **kwargs)
|
||||||
if original_context:
|
if original_context:
|
||||||
context.push(original_context)
|
context.push(original_context)
|
||||||
return context
|
return context
|
||||||
|
|
|
@ -18,7 +18,7 @@ class Engine(object):
|
||||||
|
|
||||||
def __init__(self, dirs=None, app_dirs=False, context_processors=None,
|
def __init__(self, dirs=None, app_dirs=False, context_processors=None,
|
||||||
debug=False, loaders=None, string_if_invalid='',
|
debug=False, loaders=None, string_if_invalid='',
|
||||||
file_charset='utf-8', libraries=None, builtins=None):
|
file_charset='utf-8', libraries=None, builtins=None, autoescape=True):
|
||||||
if dirs is None:
|
if dirs is None:
|
||||||
dirs = []
|
dirs = []
|
||||||
if context_processors is None:
|
if context_processors is None:
|
||||||
|
@ -38,6 +38,7 @@ class Engine(object):
|
||||||
|
|
||||||
self.dirs = dirs
|
self.dirs = dirs
|
||||||
self.app_dirs = app_dirs
|
self.app_dirs = app_dirs
|
||||||
|
self.autoescape = autoescape
|
||||||
self.context_processors = context_processors
|
self.context_processors = context_processors
|
||||||
self.debug = debug
|
self.debug = debug
|
||||||
self.loaders = loaders
|
self.loaders = loaders
|
||||||
|
|
|
@ -48,7 +48,7 @@ probably isn't the documentation you're looking for. An instance of the
|
||||||
of that backend and any attribute defaults mentioned below are overridden by
|
of that backend and any attribute defaults mentioned below are overridden by
|
||||||
what's passed by :class:`~django.template.backends.django.DjangoTemplates`.
|
what's passed by :class:`~django.template.backends.django.DjangoTemplates`.
|
||||||
|
|
||||||
.. class:: Engine(dirs=None, app_dirs=False, context_processors=None, debug=False, loaders=None, string_if_invalid='', file_charset='utf-8', libraries=None, builtins=None)
|
.. class:: Engine(dirs=None, app_dirs=False, context_processors=None, debug=False, loaders=None, string_if_invalid='', file_charset='utf-8', libraries=None, builtins=None, autoescape=True)
|
||||||
|
|
||||||
When instantiating an ``Engine`` all arguments must be passed as keyword
|
When instantiating an ``Engine`` all arguments must be passed as keyword
|
||||||
arguments:
|
arguments:
|
||||||
|
@ -63,6 +63,18 @@ what's passed by :class:`~django.template.backends.django.DjangoTemplates`.
|
||||||
|
|
||||||
It defaults to ``False``.
|
It defaults to ``False``.
|
||||||
|
|
||||||
|
* ``autoescape`` controls whether HTML autoescaping is enabled.
|
||||||
|
|
||||||
|
It defaults to ``True``.
|
||||||
|
|
||||||
|
.. warning::
|
||||||
|
|
||||||
|
Only set it to ``False`` if you're rendering non-HTML templates!
|
||||||
|
|
||||||
|
.. versionadded:: 1.10
|
||||||
|
|
||||||
|
The ``autoescape`` option was added.
|
||||||
|
|
||||||
* ``context_processors`` is a list of dotted Python paths to callables
|
* ``context_processors`` is a list of dotted Python paths to callables
|
||||||
that are used to populate the context when a template is rendered with a
|
that are used to populate the context when a template is rendered with a
|
||||||
request. These callables take a request object as their argument and
|
request. These callables take a request object as their argument and
|
||||||
|
|
|
@ -204,7 +204,9 @@ Signals
|
||||||
Templates
|
Templates
|
||||||
^^^^^^^^^
|
^^^^^^^^^
|
||||||
|
|
||||||
* ...
|
* Added the ``autoescape`` option to the
|
||||||
|
:class:`~django.template.backends.django.DjangoTemplates` backend and the
|
||||||
|
:class:`~django.template.Engine` class.
|
||||||
|
|
||||||
Tests
|
Tests
|
||||||
^^^^^
|
^^^^^
|
||||||
|
|
|
@ -295,6 +295,19 @@ applications. This generic name was kept for backwards-compatibility.
|
||||||
``DjangoTemplates`` engines accept the following :setting:`OPTIONS
|
``DjangoTemplates`` engines accept the following :setting:`OPTIONS
|
||||||
<TEMPLATES-OPTIONS>`:
|
<TEMPLATES-OPTIONS>`:
|
||||||
|
|
||||||
|
* ``'autoescape'``: a boolean that controls whether HTML autoescaping is
|
||||||
|
enabled.
|
||||||
|
|
||||||
|
It defaults to ``True``.
|
||||||
|
|
||||||
|
.. warning::
|
||||||
|
|
||||||
|
Only set it to ``False`` if you're rendering non-HTML templates!
|
||||||
|
|
||||||
|
.. versionadded:: 1.10
|
||||||
|
|
||||||
|
The ``autoescape`` option was added.
|
||||||
|
|
||||||
* ``'context_processors'``: a list of dotted Python paths to callables that
|
* ``'context_processors'``: a list of dotted Python paths to callables that
|
||||||
are used to populate the context when a template is rendered with a request.
|
are used to populate the context when a template is rendered with a request.
|
||||||
These callables take a request object as their argument and return a
|
These callables take a request object as their argument and return a
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
from template_tests.test_response import test_processor_name
|
from template_tests.test_response import test_processor_name
|
||||||
|
|
||||||
|
from django.template import EngineHandler
|
||||||
from django.template.backends.django import DjangoTemplates
|
from django.template.backends.django import DjangoTemplates
|
||||||
from django.template.library import InvalidTemplateLibrary
|
from django.template.library import InvalidTemplateLibrary
|
||||||
from django.test import RequestFactory, override_settings
|
from django.test import RequestFactory, override_settings
|
||||||
|
@ -108,3 +109,24 @@ class DjangoTemplatesTests(TemplateStringsTests):
|
||||||
'template_backends.apps.good.templatetags.good_tags',
|
'template_backends.apps.good.templatetags.good_tags',
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def test_autoescape_off(self):
|
||||||
|
templates = [{
|
||||||
|
'BACKEND': 'django.template.backends.django.DjangoTemplates',
|
||||||
|
'OPTIONS': {'autoescape': False},
|
||||||
|
}]
|
||||||
|
engines = EngineHandler(templates=templates)
|
||||||
|
self.assertEqual(
|
||||||
|
engines['django'].from_string('Hello, {{ name }}').render({'name': 'Bob & Jim'}),
|
||||||
|
'Hello, Bob & Jim'
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_autoescape_default(self):
|
||||||
|
templates = [{
|
||||||
|
'BACKEND': 'django.template.backends.django.DjangoTemplates',
|
||||||
|
}]
|
||||||
|
engines = EngineHandler(templates=templates)
|
||||||
|
self.assertEqual(
|
||||||
|
engines['django'].from_string('Hello, {{ name }}').render({'name': 'Bob & Jim'}),
|
||||||
|
'Hello, Bob & Jim'
|
||||||
|
)
|
||||||
|
|
Loading…
Reference in New Issue