Каков наилучший способ обработки бесполезных атрибутов в шаблонах Django?

Я ищу более простой способ условного добавления бесполезных атрибутов HTML, таких как disabled, в шаблон Django.

Например, в приведенном ниже фрагменте кода тег {% if %} встроен непосредственно в тег <button>, что, на мой взгляд, затрудняет чтение кода.

<button type="submit"
    id="prev-page-btn"
    class="btn btn-secondary w-50"
    name="prev-page-btn"
    {% if not page_obj.has_previous %}disabled{% endif %}>
   Previous
</button>

Есть ли более элегантное решение для этого? Я бы хотел избежать дублирования всего блока <button> только для того, чтобы контролировать наличие атрибута disabled.

Вместо того, чтобы помещать логику {% if %} непосредственно в тег, присвойте ее контекстной переменной или используйте тег {% with %}.

Например:

{% with 'disabled' if not page_obj.has_previous else '' as disabled_attr %}
<button type="submit"
    id="prev-page-btn"
    class="btn btn-secondary w-50"
    name="prev-page-btn"
    {{ disabled_attr }}>
   Previous
</button>
{% endwith %}

Здесь может помочь тег пользовательского шаблона [Django-doc], например:

# some_app/templatetags/htmlattr.py

from django.forms.utils import flatattr

from django import template

register = template.Library()


@register.simple_tag(name='html_attributes')
def html_attributes(**kwargs):
    return flatatt(kwargs)

затем мы можем загрузить этот тег шаблона в шаблон и использовать его соответствующим образом:

{% load htmlattr %}

{% with not page_obj.has_previous as no_previous %}

<button type="submit"
    id="prev-page-btn"
    class="btn btn-secondary w-50"
    name="prev-page-btn"
    {% html_attributes disabled=no_previous %}>
   Previous
</button>
{% endwith %}

Наш html_attributes позволяет работать с ключами-значениями. Если значение False или None, оно не будет включено. Если значение не является логическим, оно будет передано как значение атрибута HTML, таким образом:

<tag {% html_attributes foo='bar' qux=False bla=True %}>

будет закодировано в HTML как:

<tag foo="bar" bla>

Таким образом, мы можем заменить вышеприведенное на:

{% with not page_obj.has_previous as no_previous %}

<button {% html_attributes type='submit' id='prev-page-btn' class='btn btn-secondary w-50' name='prev-page-btn' disabled=no_previous %}>
   Previous
</button>
{% endwith %}

Django использует это flatatt для внутреннего форматирования атрибутов HTML для элементов формы.

Вам нужно будет переместить логику за пределы {% with %} и использовать традиционный блок {% if %}, чтобы задать значение:

{% if not page_obj.has_previous %}
  {% with 'disabled' as disabled_attr %}
{% else %}
  {% with '' as disabled_attr %}
{% endif %}
<button type="submit"
    id="prev-page-btn"
    class="btn btn-secondary w-50"
    name="prev-page-btn"
    {{ disabled_attr }}>
   Previous
</button>
{% endwith %}

Это работает со всеми поддерживаемыми версиями Django.

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