Is there an out-of-the-box way of checking if a template exists before including it in a Django template? Alternatives are welcome too but some of them would not work due to the particular circumstances.
在将模板包含在Django模板中之前,是否有一种开箱即用的方法检查模板是否存在?替代方案也很受欢迎,但由于特殊情况,其中一些方案不会奏效。
For example, here's an answer to a slightly different question. This is not what I'm looking for: How to check if a template exists in Django?
例如,这里有一个稍微不同的问题的答案。这不是我想要的:如何检查Django中是否存在模板?
4 个解决方案
#1
14
Assuming include
doesn't blow up if you pass it a bad template reference, that's probably the best way to go. Your other alternative would be to create a template tag that essentially does the checks in the link you mentioned.
假设如果传递一个错误的模板引用,include不会崩溃,这可能是最好的方法。您的另一种选择是创建一个模板标记,它实际上执行您提到的链接中的检查。
Very basic implementation:
非常基本的实现:
from django import template
register = template.Library()
@register.simple_tag
def template_exists(template_name):
try:
django.template.loader.get_template(template_name)
return "Template exists"
except template.TemplateDoesNotExist:
return "Template doesn't exist"
In your template:
在你的模板:
{% template_exists 'someapp/sometemplate.html' %}
That tag isn't really all that useful, so you'd probably want to create one that actually adds a variable to the context, which you could then check in an if statement or what not.
这个标签并不是很有用,所以你可能想要创建一个在上下文中添加一个变量的标签,然后你可以在if语句中进行检查。
#2
8
I encountered this trying to display a template only if it exists, and wound up with the following template tag solution:
我遇到了这样的情况:仅当模板存在时才显示模板,最后得到了以下模板标记解决方案:
Include a template only if it exists
Put the following into yourapp/templatetags/include_maybe.py
将以下内容放到app/templatetags/include_maybe.py中
from django import template
from django.template.loader_tags import do_include
from django.template.defaulttags import CommentNode
register = template.Library()
@register.tag('include_maybe')
def do_include_maybe(parser, token):
"Source: http://*.com/a/18951166/15690"
bits = token.split_contents()
if len(bits) < 2:
raise template.TemplateSyntaxError(
"%r tag takes at least one argument: "
"the name of the template to be included." % bits[0])
try:
silent_node = do_include(parser, token)
except template.TemplateDoesNotExist:
# Django < 1.7
return CommentNode()
_orig_render = silent_node.render
def wrapped_render(*args, **kwargs):
try:
return _orig_render(*args, **kwargs)
except template.TemplateDoesNotExist:
return CommentNode()
silent_node.render = wrapped_render
return silent_node
Access it from your templates by adding {% load include_maybe %}
at the top of your template, and using {% include_maybe "my_template_name.html" %}
in code.
通过在模板顶部添加{% load include_maybe %}并使用{% include_maybe "my_template_name从模板中访问它。html代码中“% }。
This approach has the nice side effect of piggy-backing the existing template include tag, so you can pass in context variables in the same way that you can with a plain {% include %}
.
这种方法有piggy支持的良好的副作用,即现有的模板包含标记,因此您可以以相同的方式传递上下文变量,而普通的{%包含%}。
Switch based on whether a template exists
However, I wanted some additional formatting on the embedding site if the template existed. Rather than writing an {% if_template_exists %}
tag, I wrote a filter that lets you work with the existing {% if %}
tag.
但是,如果存在模板,我希望在嵌入站点上添加一些其他格式。我没有编写一个{% if_template_exists %}标签,而是编写了一个过滤器,允许您使用现有的{% if %}标签。
To this end, put the following into yourapp/templatetags/include_maybe.py
(or something else)
为此,将以下内容放入您的app/templatetags/include_maybe中。py(或其他)
from django import template
from django.template.defaultfilters import stringfilter
register = template.Library()
@register.filter
@stringfilter
def template_exists(value):
try:
template.loader.get_template(value)
return True
except template.TemplateDoesNotExist:
return False
And then, from your template, you can do something like:
然后,从你的模板,你可以做一些类似的事情:
{% load include_maybe %}
{% if "my_template_name"|template_exists %}
<div>
<h1>Notice!</h1>
<div class="included">
{% include_maybe "my_template_name" %}
</div>
</div>
{% endif %}
The advantage of using a custom filter over using a custom tag is that you can do things like:
与使用自定义标记相比,使用自定义过滤器的优点在于,您可以执行以下操作:
{% if "my_template_name"|template_exists and user.is_authenticated %}...{% endif %}
instead of using multiple {% if %}
tags.
而不是使用多个{% if %}标签。
Note that you still have to use include_maybe
.
注意,您仍然需要使用include_maybe。
#3
1
I needed to conditionally include templates if they exist but I wanted to use a variable to store the template name like you can do with the regular {% include %}
tag.
我需要有条件地包含模板,如果它们存在,但是我想使用一个变量来存储模板名称,就像您可以使用常规{% include %}标签那样。
Here's my solution which I've used with Django 1.7:
这是我对Django 1.7使用的解决方案:
from django import template
from django.template.loader_tags import do_include
register = template.Library()
class TryIncludeNode(template.Node):
"""
A Node that instantiates an IncludeNode but wraps its render() in a
try/except in case the template doesn't exist.
"""
def __init__(self, parser, token):
self.include_node = do_include(parser, token)
def render(self, context):
try:
return self.include_node.render(context)
except template.TemplateDoesNotExist:
return ''
@register.tag('try_include')
def try_include(parser, token):
"""
Include the specified template but only if it exists.
"""
return TryIncludeNode(parser, token)
#4
0
include
accepts variables:
包括接受变量:
{% include template_name %}
so you could do the check in your view.
你可以在视图中做检查。
#1
14
Assuming include
doesn't blow up if you pass it a bad template reference, that's probably the best way to go. Your other alternative would be to create a template tag that essentially does the checks in the link you mentioned.
假设如果传递一个错误的模板引用,include不会崩溃,这可能是最好的方法。您的另一种选择是创建一个模板标记,它实际上执行您提到的链接中的检查。
Very basic implementation:
非常基本的实现:
from django import template
register = template.Library()
@register.simple_tag
def template_exists(template_name):
try:
django.template.loader.get_template(template_name)
return "Template exists"
except template.TemplateDoesNotExist:
return "Template doesn't exist"
In your template:
在你的模板:
{% template_exists 'someapp/sometemplate.html' %}
That tag isn't really all that useful, so you'd probably want to create one that actually adds a variable to the context, which you could then check in an if statement or what not.
这个标签并不是很有用,所以你可能想要创建一个在上下文中添加一个变量的标签,然后你可以在if语句中进行检查。
#2
8
I encountered this trying to display a template only if it exists, and wound up with the following template tag solution:
我遇到了这样的情况:仅当模板存在时才显示模板,最后得到了以下模板标记解决方案:
Include a template only if it exists
Put the following into yourapp/templatetags/include_maybe.py
将以下内容放到app/templatetags/include_maybe.py中
from django import template
from django.template.loader_tags import do_include
from django.template.defaulttags import CommentNode
register = template.Library()
@register.tag('include_maybe')
def do_include_maybe(parser, token):
"Source: http://*.com/a/18951166/15690"
bits = token.split_contents()
if len(bits) < 2:
raise template.TemplateSyntaxError(
"%r tag takes at least one argument: "
"the name of the template to be included." % bits[0])
try:
silent_node = do_include(parser, token)
except template.TemplateDoesNotExist:
# Django < 1.7
return CommentNode()
_orig_render = silent_node.render
def wrapped_render(*args, **kwargs):
try:
return _orig_render(*args, **kwargs)
except template.TemplateDoesNotExist:
return CommentNode()
silent_node.render = wrapped_render
return silent_node
Access it from your templates by adding {% load include_maybe %}
at the top of your template, and using {% include_maybe "my_template_name.html" %}
in code.
通过在模板顶部添加{% load include_maybe %}并使用{% include_maybe "my_template_name从模板中访问它。html代码中“% }。
This approach has the nice side effect of piggy-backing the existing template include tag, so you can pass in context variables in the same way that you can with a plain {% include %}
.
这种方法有piggy支持的良好的副作用,即现有的模板包含标记,因此您可以以相同的方式传递上下文变量,而普通的{%包含%}。
Switch based on whether a template exists
However, I wanted some additional formatting on the embedding site if the template existed. Rather than writing an {% if_template_exists %}
tag, I wrote a filter that lets you work with the existing {% if %}
tag.
但是,如果存在模板,我希望在嵌入站点上添加一些其他格式。我没有编写一个{% if_template_exists %}标签,而是编写了一个过滤器,允许您使用现有的{% if %}标签。
To this end, put the following into yourapp/templatetags/include_maybe.py
(or something else)
为此,将以下内容放入您的app/templatetags/include_maybe中。py(或其他)
from django import template
from django.template.defaultfilters import stringfilter
register = template.Library()
@register.filter
@stringfilter
def template_exists(value):
try:
template.loader.get_template(value)
return True
except template.TemplateDoesNotExist:
return False
And then, from your template, you can do something like:
然后,从你的模板,你可以做一些类似的事情:
{% load include_maybe %}
{% if "my_template_name"|template_exists %}
<div>
<h1>Notice!</h1>
<div class="included">
{% include_maybe "my_template_name" %}
</div>
</div>
{% endif %}
The advantage of using a custom filter over using a custom tag is that you can do things like:
与使用自定义标记相比,使用自定义过滤器的优点在于,您可以执行以下操作:
{% if "my_template_name"|template_exists and user.is_authenticated %}...{% endif %}
instead of using multiple {% if %}
tags.
而不是使用多个{% if %}标签。
Note that you still have to use include_maybe
.
注意,您仍然需要使用include_maybe。
#3
1
I needed to conditionally include templates if they exist but I wanted to use a variable to store the template name like you can do with the regular {% include %}
tag.
我需要有条件地包含模板,如果它们存在,但是我想使用一个变量来存储模板名称,就像您可以使用常规{% include %}标签那样。
Here's my solution which I've used with Django 1.7:
这是我对Django 1.7使用的解决方案:
from django import template
from django.template.loader_tags import do_include
register = template.Library()
class TryIncludeNode(template.Node):
"""
A Node that instantiates an IncludeNode but wraps its render() in a
try/except in case the template doesn't exist.
"""
def __init__(self, parser, token):
self.include_node = do_include(parser, token)
def render(self, context):
try:
return self.include_node.render(context)
except template.TemplateDoesNotExist:
return ''
@register.tag('try_include')
def try_include(parser, token):
"""
Include the specified template but only if it exists.
"""
return TryIncludeNode(parser, token)
#4
0
include
accepts variables:
包括接受变量:
{% include template_name %}
so you could do the check in your view.
你可以在视图中做检查。