This change:
* Makes the InclusionNode cache-safe by removing render-time side effects
to its nodelist.
* Ensures the render_context stack is properly scoped and reset by updating
the render call to use Template.render rather than Nodelist.render.
Rendering a Jinja template with self in the context threw an error.
While self is a reserved variable in Jinja, including self in the
context is not an error, so Django should respect that.
This patch does three major things:
* Merges the django.template.debug implementation into django.template.base.
* Simplifies the debug implementation.
The old implementation copied debug information to every token and node.
The django_template_source attribute was set in multiple places, some
quite hacky, like django.template.defaulttags.ForNode.
Debug information is now annotated in two high-level places:
* Template.compile_nodelist for errors during parsing
* Node.render_annotated for errors during rendering
These were chosen because they have access to the template and context
as well as to all exceptions that happen during either the parse or
render phase.
* Moves the contextual line traceback information creation from
django.views.debug into django.template.base.Template. The debug views now
only deal with the presentation of the debug information.
This may cause some backwards compatibility issues, but may also
resolve security issues in third party projects that fail to heed warnings
in our documentation.
Thanks Markus Holtermann for help with tests and docs.
Explicitly checking for django.template.Template subclasses is
preferrable to duck-typing because both the django.template.Template and
django.template.backends.django.Template have a render() method.
Thanks spectras for the report.
This significantly improves performance on PyPy. The previous
implementation would generate a new class on every single request,
which is relatively slow.
Specifically in rendering shortcuts, template responses, and class-based
views that return template responses.
Also added a test for render_to_response(status=...) which was missing
from fdbfc980.
Thanks Tim and Carl for the review.
A deprecation path is required because the return type of
django.template.loader.get_template changed during the
multiple template engines refactor.
test_csrf_token_in_404 was incorrect: it tested the case when the
hardcoded template was rendered, and that template doesn't depend on the
CSRF token. This commit makes it test the case when a custom template is
rendered.
This is for consistency with Template.render.
It adds a little bit of knowledge about HTTP requests in
django.template.loader but I think consistency trumps purity.
This is the expected behavior, but given RequestContext's tortuous
implementation, a straightforward use of its API results in the
opposite.
This commits fixes a regression that must have happened at different
points in the multiple templates engine refactor for different features.
This avoids leaving projects silently vulnerable when this option is set
to a string instead of a one-item tuple containing that string, a very
common misconfiguration.
Previously, when a template was rendered with RequestContext, inclusion
tags were rendered with a plain context, losing additional information
available in the RequestContext.
The (admittedly bizarre) implementation of RequestContext.new() has the
side-effect of not running template context processors, making this
change backwards-compatible.
This commit changes the return type of these two functions. Instead of
returning a django.template.Template they return a backend-specific
Template class that must implement render(self, context).
Since this package is going to hold both the implementation of the Django
Template Language and the infrastructure for Multiple Template Engines,
it should be untied from the DTL as much as possible within our
backwards-compatibility policy.
Only public APIs (i.e. APIs mentioned in the documentation) were left.
Refs #7261 -- Made strings escaped by Django usable in third-party libs.
The changes in mark_safe and mark_for_escaping are straightforward. The
more tricky part is to handle correctly objects that implement __html__.
Historically escape() has escaped SafeData. Even if that doesn't seem a
good behavior, changing it would create security concerns. Therefore
support for __html__() was only added to conditional_escape() where this
concern doesn't exist.
Then using conditional_escape() instead of escape() in the Django
template engine makes it understand data escaped by other libraries.
Template filter |escape accounts for __html__() when it's available.
|force_escape forces the use of Django's HTML escaping implementation.
Here's why the change in render_value_in_context() is safe. Before Django
1.7 conditional_escape() was implemented as follows:
if isinstance(text, SafeData):
return text
else:
return escape(text)
render_value_in_context() never called escape() on SafeData. Therefore
replacing escape() with conditional_escape() doesn't change the
autoescaping logic as it was originally intended.
This change should be backported to Django 1.7 because it corrects a
feature added in Django 1.7.
Thanks mitsuhiko for the report.
Since RequestContext doesn't know its Engine until it's passed to
Template.render() -- and cannot without breaking a widely used public
API -- an elaborate hack is required to apply context processors.
Passed the engine instance to loaders. This is a prerequisite for
looking up configuration on the engine instance instead of global
settings.
This is backwards incompatible for custom template loaders that override
__init__. However the documentation doesn't talk about __init__ and the
way to pass arguments to custom template loaders isn't specified. I'm
considering it a private API.
This change preserves backwards-compatibility for a very common misuse
of render_to_response which even occurred in the official documentation.
It fixes that misuse wherever it happened in the code base and docs.
Context.__init__ is documented as accepting a dict and nothing else.
Since Context is dict-like, Context(Context({})) could work to some
extent. However, things get complicated with RequestContext and that
gets in the way of refactoring the template engine. This is the real
rationale for this change.
They were deprecated in Django 1.2 but not all the supporting code was
removed in Django 1.4. Since the remaining code was unlikely to be
functional (pun intended) e.g. it would crash unless the loader
function had an is_usable attribute, this commit completes the removal
immediately instead of starting another deprecation path.
This change has the nice side effect of removing code that ran at import
time and depended on the app registry at module level -- a notorious
cause of AppRegistryNotReady exceptions.
Since it isn't branded as a test utility any more and could be used for
other purposes than test code, that prefix no longer makes sense.
It wasn't used anywhere either.
Reformatted the code of base.Loader according to modern standards.
Turned the test template loader into a regular locmem.Loader -- but
didn't document it.
Added a normal deprecation path for BaseLoader which is a public API.
Added an accelerated deprecation path for TestTemplateLoader which is
a private API.
Added a test for the condition safe_join is designed to prevent.
Previously, a generic ValueError was raised. It was impossible to tell
an intentional exception raised to implement safe_join's contract from
an unintentional exception caused by incorrect inputs or unexpected
conditions. That resulted in bizarre exception catching patterns, which
this patch removes.
Since safe_join is a private API and since the change is unlikely to
create security issues for users who use it anyway -- at worst, an
uncaught SuspiciousFileOperation exception will bubble up -- it isn't
documented.
The docstring of FilterExpression said that it shouldn't be
instantiated from anywhere but the get_filters_from_token
helper function.
However, that helper function was deleted in commit
3ede006fc9 and FilterExpression
is instantiated from inside the compile_filter help function.
``get_template_from_string`` default arguments were breaking
``assertTemplateUsed``. The solution has been to return only the names of the
templates with a ``name`` attribute distinct of ``None``. The default ``name``
kwarg of ``Template`` has been changed to ``None``, more pythonic than ``'<Unknown
Template>'``.
Merged BaseIncludeNode, ConstantIncludeNode and Include node.
This avoids raising TemplateDoesNotExist at parsing time, allows recursion
when passing a literal template name, and should make TEMPLATE_DEBUG behavior
consistant.
Thanks loic84 for help with the tests.
Fixed#3544, fixed#12064, fixed#16147
This function is now the de facto standard function for rendering values in a
template, and is imported by two other built-in template modules. It shouldn't
have a leading underscore.
The content of ifchanged template tag was rendered twice: first time, to
compare it with the previous value and the second time, to return the
rendered output.
Previously, the ifchanged node stored state on `self._last_seen`,
thereby giving undesired results when the node is reused by another
thread at the same time (e.g. globally caching a Template object).
Thanks to akaihola for the report and Diederik van der Boor and
Bas Peschier for the patch.