Kaydet (Commit) 19a5f6da authored tarafından Aaron Elliot Ross's avatar Aaron Elliot Ross Kaydeden (comit) Tim Graham

Fixed #25469 -- Added autoescape option to DjangoTemplates backend.

Thanks Aymeric for the initial patch and Carl for review.
üst a8f05f40
...@@ -23,6 +23,7 @@ class DjangoTemplates(BaseEngine): ...@@ -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): ...@@ -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): ...@@ -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): ...@@ -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): ...@@ -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): ...@@ -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 ...@@ -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`. ...@@ -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 ...@@ -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. ...@@ -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
......
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): ...@@ -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 &amp; Jim'
)
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment