Получить тип виджета формы Django из шаблона - PullRequest
41 голосов
/ 27 ноября 2009

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

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

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

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

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

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

Ответы [ 5 ]

43 голосов
/ 27 ноября 2009

Создание шаблона тега может работать? Что-то вроде 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 шаблона.

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

35 голосов
/ 17 июня 2010

Отслеживание принятого ответа - расширенный 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>
19 голосов
/ 06 июня 2014

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

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

код фильтра:

from django import template
register = template.Library()

@register.filter('fieldtype')
def fieldtype(field):
    return field.field.widget.__class__.__name__
15 голосов
/ 20 октября 2017

Начиная с 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 %}
0 голосов
/ 20 июня 2018

Возможно, стоит обратить внимание современных читателей, что 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.

...