AutoEscaping Alternative
Escaping is important for VariableNodes ({{ object.name }}
tags). A filter is usually applied to each of these nodes.
The straight-forward solution is to provide a block tag which can automatically add filters (for html escaping, |escape
) to any variable tag defined within the block.
The solution is to provide a {% finalfilter %}
block tag.
If a tag has already been "finalized" in the view (ie. it doesn't need the filters added to it), a specific new filter |finalized
can be added to that variable tag.
To avoid unwanted double escaping, if a tag explictly already uses a filter declared in finalfilter
, it will not be added again.
Keep it Simple
There is no complex code hidden underneath deciding on what should/shouldn't be escaped. All that's happening is one or more common filters are being applied automatically to every variable tag defined within the finalfilter
block.
Explicit is good
The template author has to use finalfilter
explicitly. It does work across {% extend %}
ed pages however, but some amount of implicitness is required for this to be a useful tag.
Not just HTML escaping
Any filter can be used with the finalfilter
tag.
Example
base.html
:
{% load filtertags %} {% finalfilter escape %} <head> <title>Test Escaping</title> </head> <body> <div id="content"> {% block content %}{% endblock %} </div> </body> </html> {% endfinalfilter %}
index.html
:
{% extends "base.htm" %} {% block content %} <h1>{% object.title %}</h1> <p>{% object.details %}</p> {% endblock %}
edit.html
:
{% extends "base.html" %} {% block content %} <h1>Edit {% object.title %}</h1> {% load filtertags %} {% finalfilter finalized %} <p><label for="id_title">Title</label> {{ form.title }}</p> <p><label for="id_details">Details</label> {{ form.details }}</p> {% endfinalfilter %} {% endblock %}
One gotcha to be aware of: if you set {% finalfilter escape %}
in a base template and then want to use the finalized
filter in a template that extends it, you must {% load filtertags %}
in the template or finalized
won't be found. This is exactly how things should work (see here), but since the finalfilter
tag spans included templates, it may not be immediately obvious.
Try It Out
Basic instructions for using the file below:
- Create a
templatetags
directory inside of an app listed in theINSTALLED_APPS
of yoursettings.py
- Make a blank file
__init__.py
(that's two underscores before and after) in thetemplatetags
folder - Copy the
filtertags.py
file into that folder (rename the latest file listed below to that)
Attachments (2)
-
filtertags.py
(4.8 KB
) - added by 18 years ago.
finalfilter
template tag -
filtertags.2.py
(3.9 KB
) - added by 18 years ago.
Newer, simpler implementation
Download all attachments as: .zip