Есть ли чистый способ снизить цикломатическую сложность шаблонов Django?
У меня есть шаблон Django, над которым я работаю, который принимает объект, имеющий несколько свойств, и добавляет различные теги на основе этих свойств. Например, если object.bold == True
он добавляет тег <b></b>
, а если object.strikethrough == True
он добавляет тег <strike></strike>
. Я видел несколько других сообщений, в которых предлагается вложить if'ы, например:
{% for object in objects %}
{% if object.bold == True %}
{% if object.strikethrough == True %}
<b><strike>{{object.name}}</strike></b>
{% else %}
<b>{{object.name}}</b>
{% endif %}
{% else %}
{% if object.strikethrough==True %}
<strike>{{object.name}}</strike>
{% else %}
{{object.name}}
{% endif %}
{% endif %}
{% endfor %}
Этот код причиняет мне боль. Я также видел некоторую извращенную логику с оберткой только начальных тегов в утверждениях if
. Опять же, больно вводить консольные ошибки.
Есть ли лучший, более чистый способ достичь этого результата без вложенных if? Я склоняюсь к созданию пользовательского тега Django, но это кажется излишеством для чего-то, что, как я надеюсь, может быть проще.
Другой возможностью было бы просто использовать css класс, например
css-файл:
.myboldTrue {
font-weight: bold;
}
.mystrikethroughTrue {
text-decoration: line-through;
}
html-файл:
{% for object in objects %}
<span class="mybold{{ object.bold }} mystriketrough{{ object.strikethrough }}"> {{object.name}} </span>
{% endfor %}
В итоге я написал собственный декоратор, который сработал достаточно хорошо.
В myapp/templates/my_template.html
у меня есть что-то, что выглядит следующим образом:
{% load decorator_tags.py %}
{% for object in objects %}
{% get_decorators object as result %}
{{ result }}
{% endfor %}
Затем в myapp/templatetags/get_decorators.py
у меня есть что-то, что выглядит следующим образом:
from django import template
from django.utils.safestring import mark_safe
register = template.Library()
@register.simple_tag(name='get_decorators')
def get_decorators(object):
prepend_string = ''
append_string = ''
if object.bold:
prepend_string = '<b>' + prepend_string
append_string = append_string + '</b>'
if object.strikethrough:
prepend_string = '<strike>' + prepend_string
append_string = append_string + '</strike>'
return mark_safe(prepend_string + object.name + append_string)
Хотя это гораздо больше кода, он выглядит чище, придерживается Django вместо использования причудливого HTML или CSS, сохраняет мои шаблоны тонкими, и является многоразовым. Возможно, я могу почистить логику get_decorators
, но сейчас я могу сделать это с минимальными изменениями кода.
У меня ушло немного времени, чтобы разобраться во всем, поэтому я решил опубликовать это здесь на случай, если кто-то еще столкнется с той же проблемой.