Summary:
How should I reference static files in a handlebars-part in a django template? I can use handlebars if I use verbatim
tags, but then I can't use django's static
tag.
Details
While converting an app to Django, I came across a part that uses handelbars.js
for rendering ajax-call-results. Via, amongst others, "Handlebars.js in Django templates" I found out about the {% verbatim %}
tag.
A simple piece of handlebars works fine with this. But I also have a part where images are dynamically shown based on the result, which looks something like this:
<img src="path/{{ result }}.png">
Now while this works fine if I set the path manually, I believe in Django it is good practice to reference your static files like so:
<img src="{% static 'path/file.png' %}">
Just getting a static_url
constant isn't advised, see for instance this blog
So unless someone has a real compelling reason to fix it otherwise, I believe it is best to use the {% static %}
method.
The naive solution would be to combine the 2 techniques, and literally spray the template with verbatim/endverbatim. Apart from the fact that this looks ugly, illegible and seems like a bad idea from the start, it also doesn't work.
{% verbatim %}
<!-- handlebars -->
{% endverbatim %}
<img src="{% static 'path{% verbatim %}{{ result }}{% endverbatim %}' %}">
{% verbatim %}
<!-- handlebars -->
{% endverbatim %}
This ends in tears, as the result is
TemplateSyntaxError at /
Could not parse the remainder: ''path{%' from ''path{%'
It might be possible to generate the correct static url on the backend side, and render that. But the backend shouldn't be aware of what image we want to show in the template.
Only solution might be to do an extra call to the backend with the 'relative' string (e.g. path/result.png
) to the backend, and ask for the correct static link? This isn't that hard, but requires an extra call, which shouldn't be the case.
So how do I correctly reference these static files ?
Using the collectstatic command, Django looks for all static files in your apps and collects them wherever you told it to, i.e. the STATIC_ROOT . In our case, we are telling Django that when we run python manage.py collectstatic , gather all static files into a folder called staticfiles in our project root directory.
You’d like to not delineate the boundary between handlebar tags and Django tags. Perhaps the cleanest solution is to explicitly declare handlebar tags as so:
{{ "handlebars_variable"|handlebars }}
where the filter handlebars
is defined as so (source):
from django import template
register = template.Library()
@register.filter
def handlebars(value):
# str.format would require ugly escaping, so we use '%'
return '{{%s}}' % value
But that’s not enough: You want to pass a handlebars tag to static
, and even with the filter you can’t do that directly. But perhaps you could try using with:
{% with "handlebars_variable"|handlebars as handlebars_tag %}
<img src="{% static handlebars_tag %}">
{% endwith %}
But even that’s not enough. You want to prepend path/
. There are multiple options for you:
add
filter based on this answer and nested with
statements (ugh).setvar
like done so here (if you’d like).You could define an ad hoc template tag like this (perhaps inelegant):
@register.filter
def static_result_path(value):
return 'result/{{%s}}' % value
and then change the template code to:
<img src="{% static "handlebars_variable"|static_result_path %}">
Use get_static_prefix
(the simplest!):
<img src="{% get_static_prefix %}result/{{ "handlebars_variable"|handlebars }}" />
(And there’s always Jinja.)
Even though django templates don't support any sort of escape character, they do support the templatetag tag that allows you to embed the special text in this case.
Assuming you don't have too many handlebars substitutions, you could just do something like this as needed:
<img src="{% get_static_prefix %}path/{% templatetag openvariable %} result {% templatetag closevariable %}.png" />
However, if you have a lot of substitutions to do, using a custom filter as per yarthathrock's answer is more succinct and so probably easier to maintain in the long run.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With