Есть ли чистый способ снизить цикломатическую сложность шаблонов 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, но сейчас я могу сделать это с минимальными изменениями кода.

У меня ушло немного времени, чтобы разобраться во всем, поэтому я решил опубликовать это здесь на случай, если кто-то еще столкнется с той же проблемой.

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