I am trying to use the templatetag described in SO answer: https://stackoverflow.com/a/6217194/493211 in a project using Django 1.4.3 (with Python 2.7.2).
I adapted it like this:
from django import template
register = template.Library()
@register.filter
def template_exists(template_name):
try:
template.loader.get_template(template_name)
return True
except template.TemplateDoesNotExist:
return False
So that I could use it like this in another template:
{% if 'profile/header.html'|template_exists %}
{% include 'profile/header.html' %}
{% else %}
{% include 'common/header.html' %}
{% endif %}
This way, I could have avoided using solutions such as changing the order of my apps in INSTALLED_APPS.
However, it does not work. If the template does not exist, then the exception is raised within the stack/console but it is not propagated up to get_template(..)
(from inside this statement), and thus not to my foolish API. Hence, this blows up in my face during the rendering. I uploaded the stacktrace to pastebin
Is this a wanted behavior from Django?
I ended up stop doing foolish things as is. But my question would remain.
What about a custom tag? This doesn't provide the full functionality of include
but seems to meet the needs in the question.:
@register.simple_tag(takes_context=True)
def include_fallback(context, *template_choices):
t = django.template.loader.select_template(template_choices)
return t.render(context)
Then in your template:
{% include_fallback "profile/header.html" "common/header.html" %}
I found some kind of an answer to my question so I am posting it here for future refence.
If I use my template_exists filter like this
{% if 'profile/header.html'|template_exists %}
{% include 'profile/header.html' %}
{% else %}
{% include 'common/header.html' %}
{% endif %}
and if profile/header.html
does not exist, then the TemplateDoesNotExist gets strangely propagated at page load and I get a server error. However, if instead, I use this in my template:
{% with 'profile/header.html' as var_templ %}
{% if var_templ|template_exists %}
{% include var_templ %}
{% else %}
{% include 'common/header.html' %}
{% endif %}
{% endwith %}
Then, it works like a charm!
Obviously, I could have used
django.template.loader.select_template(['profile/header.html','common/header.html'])
in the view (from this SO answer). But I am using a CBV which I wanted to keep rather generic and this was called from the main template. And also I thought it would be nice to have my site working if this apps goes down for whatever reason. If this seems silly to you, please leave a comment (or yet a better answer).
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