从模板中获取Django表单小部件的类型

时间:2009-11-27 17:29:11

标签: django django-templates django-forms

我正在遍历表单的字段,对于某些字段,我想要稍微不同的布局,需要更改HTML。

为了准确地做到这一点,我只需要知道小部件类型。它的类名或类似的东西。在标准的python中,这很容易! field.field.widget.__class__.__name__

不幸的是,您不允许访问模板中的下划线变量。 大!

可以测试field.field.widget.input_type,但这仅适用于文字/密码<input ../>类型。我需要更多的解决方案。

对我而言,无论它看起来多么困难,最适合在模板级别执行此操作。我已经将处理字段HTML的代码外包给了一个单独的模板,该模板包含在字段循环中。这意味着它在ModelForm和标准Form之间是一致的(如果我写了一个中间的Form类,则不会出现这种情况)。

如果您能看到一种不需要我编辑20多种形式的通用方法,请告诉我!

6 个答案:

答案 0 :(得分:43)

制作模板标签可能有效吗?像field.field.widget|widget_type

这样的东西

来自Oli的编辑:好点!我刚写了一个过滤器:

from django import template
register = template.Library()

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

现在{{ object|klass }}呈现正确。现在我只需要弄清楚如何在模板的if语句中使用它。

从Oli#2编辑:我需要在if-statetement in-template中使用结果,所以我只是将所有逻辑转移到templatetag中。魔法。谢谢你让我朝着正确的方向发展。

答案 1 :(得分:35)

跟进接受的答案 - Django 1.2中的增强型if tag允许您在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>

答案 2 :(得分:19)

根据Oli和rinti的回答:我使用了这个,我觉得它有点简单:

模板代码:{{ field|fieldtype }}

过滤代码:

from django import template
register = template.Library()

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

答案 3 :(得分:14)

从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 %}

答案 4 :(得分:0)

也许值得向当代读者指出,django-widget-tweaks为此提供了field_typewidget_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模板标记。

答案 5 :(得分:0)

您可以使每个管理表单的视图都从自定义通用视图继承,在此视图中,您将模板中所需的元数据加载到上下文中。通用表单视图应包含以下内容:

class CustomUpdateView(UpdateView):
    ...
    def get_context_data(self, **kwargs):
       context = super().get_context_data(**kwargs)
       ...
       for f, value in context["form"].fields.items():
          context["form"].fields[f].type = self.model._meta.get_field(f).get_internal_type()
       ...
       return context

在模板中,您可以通过field.field访问这些自定义属性:

{% if field.field.type == 'BooleanField' %}
     <div class="custom-control custom-checkbox">
     ...
     </div>
{% endif %}

如果需要除字段类型以外的其他内容,则可以使用PyCharm或Visual Studio Code调试器查看所有可用的元数据。