Как определить, является ли блок шаблона пустым/пустым в 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? Я хочу сделать так, чтобы на моей домашней странице в заголовке не было "-", а было просто "Заголовок сайта". Я думаю, что лучшим способом будет сделать что-то похожее на это:

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

... но я никак не могу понять, как определить длину {% block title %}, которая передается из шаблона страницы.

Исходя из моего понимания документации, тег block не может быть присвоен переменной (по крайней мере, я не смог найти обходной путь), и значение не может быть повторно использовано в другом месте страницы. Возможно, это связано с тем, как модель наследования шаблонов относится к этому:

Это ограничение существует потому, что тег блока работает в "обоих" направлениях. То есть, тег блока не просто предоставляет отверстие для заполнения - он также определяет содержимое, которое заполняет отверстие в родителе.

Однако можно добиться желаемых результатов с помощью блока {% filter %}, поскольку он фильтрует содержимое внутри блока и не требует переменной. Есть чистый и не совсем чистый способ справиться с этим.


Чистый способ: Определите пользовательский фильтр

Следуя шагам в Написание пользовательских фильтров шаблонов, напишите фильтр 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, вы можете просто использовать более подходящее условие, если это необходимо.

Теперь это можно загрузить в 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.

Примечание: Я не полностью проверил детали вокруг безопасных строк и автозавершения, поскольку оба параметра фильтра выбираются разработчиком. Пожалуйста, ознакомьтесь с дополнительными деталями в документации, если вы планируете использовать этот фильтр с более сложным вводом или с пользовательским вводом.


Хакерский, но простой способ: Используйте фильтры default и add

Этот метод использует встроенные фильтры и документированное поведение, но он не очень читабелен/интуитивно понятен, поэтому я бы избегал его использования. Просто замените тег <title> на

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

Это основывается на следующем поведении add, выделение мое:

Сначала этот фильтр попытается привести оба значения к целым числам. Если это не удастся, он попытается сложить значения в любом случае. Это сработает для некоторых типов данных (строки, список и т.д.) и не сработает для других. Если это не удастся, результатом будет пустая строка.

Проблема в том, что при использовании просто add всегда ставится тире (даже в пустом случае), а join рассматривает строки как список, поэтому вставляет тире между всеми символами. Но если значение default не является строкой, это не работает, так как ' -' не может быть преобразовано в целое число (оно не преобразует 0 в '0', поэтому int + str не работает).

Результаты те же, что и в первом методе, непустой блок не сработает default и приведет к About Us - Website Title, а пустой блок останется пустым и приведет к Website Title.

Вернуться на верх