Как определить, является ли блок шаблона пустым/пустым в 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.