it-roy-ru.com

Получить тип виджета формы Django из шаблона

Я перебираю поля формы, и для определенных полей я хочу немного другой макет, требующий измененного HTML.

Чтобы сделать это точно, мне просто нужно знать тип виджета. Его имя класса или что-то подобное. В стандартном питоне это легко! field.field.widget.__class__.__name__

К сожалению, вам не разрешен доступ к переменным подчеркивания в шаблонах. Отлично!

Вы можете проверить field.field.widget.input_type, но это работает только для типов текст/пароль <input ../>. Мне нужно больше разрешения, что это.

Для меня, как бы сложно это ни выглядело, имеет смысл сделать это на уровне шаблона. Я передал часть кода, который обрабатывает HTML для полей, в отдельный шаблон, который включается в цикл поля. Это означает, что он согласован между ModelForms и стандартными Forms (что было бы неверно, если бы я написал промежуточный класс Form).

Если вы видите универсальный подход, который не требует от меня редактирования 20 с лишним форм, дайте мне знать тоже!

40
Oli

Начиная с Django 1.11, вы можете просто использовать widget.input_type. Пример:

{% for field in form.visible_fields %}
    <input type="{{ field.field.widget.input_type }}"
           id="{{ field.id_for_label }}"
           name="{{ field.html_name }}"
           placeholder="{{ field.label }}"
           maxlength="{{ field.field.max_length }}" />
{% endfor %}
13
Ivan Ogai

Создание шаблона тега может работать? Что-то вроде field.field.widget|widget_type

Правка от Оли: Хороший вопрос! Я только что написал фильтр:

from Django import template
register = template.Library()

@register.filter('klass')
def klass(ob):
    return ob.__class__.__name__

И теперь {{ object|klass }} рендерится правильно. Теперь я просто должен выяснить, как использовать это внутри оператора if шаблона.

Правка из Оли # 2: мне нужно было использовать результат этого в выражении if в шаблоне, поэтому я просто перенес всю эту логику в тег шаблона. Магия. Спасибо, что подтолкнул меня в правильном направлении.

43
rinti

Вслед за принятым ответом - расширенный if tag в Django 1.2 позволяет использовать фильтры в сравнениях if tag. Теперь вы можете сделать свой собственный HTML/логику в шаблоне следующим образом:

<ul>
{% for field in form.fields %}
  <li>
    {% if field.field.widget|klass == "Textarea" %}
    <!-- do something special for Textarea -->
    <h2>Text Areas are Special </h2>
    {% else %}      
      {{ field.errors }}
      {{ field.label_tag }}
      {{ field }}
    {% endif %}

  </li>
{% endfor %}
</ul>
35
zlovelady

После ответа от Оли и Ринти: я использовал этот, и я думаю, что это немного проще:

код шаблона: {{ field|fieldtype }}

код фильтра: 

from Django import template
register = template.Library()

@register.filter('fieldtype')
def fieldtype(field):
    return field.field.widget.__class__.__name__
17
Piotr Szachewicz

Возможно, стоит обратить внимание современных читателей, что Django-widget-tweaks предоставляет для этой цели фильтры шаблонов field_type и widget_type, возвращая имена соответствующих классов в нижнем регистре. В приведенном ниже примере я также показываю вывод свойства input_type для виджета поля (начиная с Django 1.11), что также может быть полезно.

forms.py:

class ContactForm(forms.Form):
    name = forms.CharField(
        max_length=150,
        required=True,
        label='Your name'
    )

template.html:

{% load widget_tweaks %}

{% for field in form.visible_fields %}
{{ field.label }}
{{ field.field.widget.input_type }}
{{ field|field_type }}
{{ field|widget_type }})
{% endfor %}

Результат:

Your name
text
charfield
textinput

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

0
BigglesZX