在 Django 中,如何确定模板块是否为 empty/blank?

How to determine if a template block is empty/blank in Django?

我正在为我的网站使用 Django 模板,我有一个网页标题的模板块:我有一个基本模板 (base.html),它按如下方式制定 <title> 元素:

<title>{% block title %}{%endblock %} - Website Title</title>

然后,在每个页面模板中,我像这样放置一个块:

{% block title %}Webpage Name Here, e.g. About Us{% endblock %}

然后会给我:<title>Webpage Name Here, e.g. About Us - Website Title</title>

有没有办法在基本模板中以编程方式确定 title 块的 size/length/content?我想让它在我的主页上,标题中没有“-”,它只是说“网站标题”。我认为最好的方法是做类似的事情:

<title>{% block title %}{% end block %}{% if title|length > 0} - {/if}Website Title</title>

...但我终生无法弄清楚如何确定从页面模板传递的 {% block title %} 的长度。

根据我对文档的理解,block 标记不能分配给变量(至少我想不出解决方法)并且该值不能在页面的其他地方重复使用。这可能是因为模板继承模型如何对待它:

This limitation exists because a block tag works in “both” directions. That is, a block tag doesn’t just provide a hole to fill – it also defines the content that fills the hole in the parent.

但是,使用 {% filter %} 块可以达到您想要的结果,因为它会过滤块内的内容并且不特别要求 variable.There 是一种干净的方式并且sort-of 处理这个的 hacky 方式。


清洁方式:定义自定义过滤器

按照 Writing custom template filters 中的步骤,编写一个 suffix 过滤器,仅在值不为空时才连接字符串。

# filename: suffix.py
from django import template
from django.template.defaultfilters import stringfilter

register = template.Library()

@register.filter
@stringfilter
def suffix(value, args):
    return value + str(args) if value else value

@stringfilter 强制 value 首先被强制转换为字符串,因此 '' 应该是唯一的虚假值。但由于这是在 python 文件中,因此如有必要,您可以只使用 more-suited 条件。

现在可以按如下方式在 base.html 中加载(load 之后的参数必须是以前的文件名):

{% load suffix %}
<!DOCTYPE html>
<html lang="en">
    <head>
        <title>{% filter suffix:' -' %}{% block title %}{% endblock title %}{% endfilter %} Website Title</title>
    </head>

    <body>
        {% block content %}{% endblock content %}
    </body>
</html>

现在如果子 HTML 文件像 {% block title %}About Us{% endblock title %} 一样覆盖块,您将得到 About Us - Website Title。如果它不包含该块,您将得到 Website Title.

注意: 我还没有完全检查有关安全字符串和 auto-escaping 的详细信息,因为过滤器的两个参数都是由开发人员选择的。如果您打算将此过滤器用于更复杂的输入或用户输入,请查看 the docs 中的其他详细信息。


笨拙但简单的方法:使用 defaultadd 过滤器

此方法使用 built-in 过滤器和记录的行为,但它不是很 readable/intuitive 所以我会避免使用它。只需将 <title> 标签替换为

<title>{% filter default:0|add:' -' %}{% block title %}{% endblock title %}{% endfilter %} Website Title</title>

这依赖于 add 的以下行为,强调我的:

This filter will first try to coerce both values to integers. If this fails, it’ll attempt to add the values together anyway. This will work on some data types (strings, list, etc.) and fail on others. If it fails, the result will be an empty string.

我遇到的问题是只使用 add 总是会放一个破折号(即使在空的情况下),而 join 将字符串视为一个列表,所以在每个字符串之间插入一个破折号特点。但是如果 default 值不是字符串,它会失败,因为 ' -' 不能被强制转换为整数(它不会将 0 转换为 '0',所以 int + str行不通)。

结果与第一种方法相同,non-empty块不会触发default并导致About Us - Website Title,而空块保持为空导致Website Title.