Adding a new template filter in Django 1.9, and a template tag annoyance
As the result of my discovery about Django's timesince
introducing
nonbreaking spaces, I wanted to fix this.
Fixing this requires coding up a new template filter and then wiring
it into Django, which took me a little bit of flailing around. I
specifically picked Django 1.9 as my target, because 1.9 supports
making your new template filters and tags available by default without
a '{% load ... %}
' statement and this matters to us.
When you are load
'ing new template widgets, your files have to
go in a specific and somewhat annoying place in your Django app.
Since I wasn't doing this, I was free to shove my code into a
normal .py
file. My minimal filter is:
from django import template from django.template.defaultfilters import stringfilter register = template.Library() @register.filter @stringfilter def denonbreak(value): """Replace non-breaking spaces with plain spaces.""" return value.replace(u"\xa0", u" ")
The resulting filter is called denonbreak
.
Although the documentation doesn't say so explicitly, you are
specifically handed a Unicode string and so interacting with it
using plain strings may not be reliable (or work at all). I suppose
this is not surprising (and people using Python 3 expect that
anyways).
To add your filter(s) and tag(s) as builtins, you make use of a new
Django 1.9 feature in the normal template backend
when setting things up in settings.py
. This is easiest to show:
TEMPLATES = [ { 'BACKEND': 'django.template.backends.django.DjangoTemplates', [...] 'OPTIONS': { 'builtins': ['accounts.tmplfilters'], [...]
(Do not get diverted to 'libraries'
; it is for something else.)
At this point you might ask why I care about not needing to {% load %}
my filter. The answer is one of the features of Django templates, which
is that there is no good way to suppress newlines at the end of template
directives.
Suppose you have a template where you want to use your new tag:
{% load something %} The following pending account requests haven't been handled for at least {{cutoff|timesince|denonbreak}}: [...]
Django will remove the {% load %}
, but it won't remove the newline
after it. Thus your rendered template will wind up starting with a
blank line. In HTML this is no problem; surplus blank lines silently
disappear when the browser renders the page. But in plain text it's
another story, because now that newline is sticking around, clearly
visible and often ugly. To fix it you must stick the {% load %}
at the start of the first real line of text, which looks ugly in
the actual template.
({% if %}
is another template tag that will bite you in plaintext
because of this. Basically any structuring tag will. I really wish
Django had an option to suppress the trailing newline in these cases,
but as far as I know it doesn't.)
This issue is why I was willing to jump to Django 1.9 and use
the 'builtins'
feature, despite what everyone generally says
about making custom things be builtins. I just hate what happens
to plaintext templates otherwise. Ours are ugly enough as it is
because of other tags with this issue.
Comments on this page:
|
|