【问题标题】:Get type of Django form widget from within template从模板中获取 Django 表单小部件的类型
【发布时间】:2010-12-21 01:26:05
【问题描述】:

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

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

很遗憾,您无权访问模板中的下划线变量。 太棒了!

可以测试field.field.widget.input_type,但这仅适用于文本/密码<input ../> 类型。我需要更多的分辨率。

对我来说,无论看起来多么困难,在模板级别执行此操作是最有意义的。我已经将处理字段 HTML 的部分代码外包给了一个单独的模板,该模板包含在字段循环中。这意味着它在 ModelForms 和标准 Forms 之间是一致的(如果我编写了一个中间 Form 类就不会这样)。

如果您能看到不需要我编辑 20 多个表单的通用方法,也请告诉我!

【问题讨论】:

标签: django django-templates django-forms


【解决方案1】:

制作模板标签可能有用吗?类似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 语句中使用结果,所以我只是将所有逻辑转移到模板标签中。魔法。感谢您为我指明了正确的方向。

【讨论】:

  • 感谢您的解决方案。关于编辑 #2 - 使用 Django 1.2 中增强的 if tags,您可以直接在模板中进行这些小部件类型比较。我发布了一个示例作为单独的答案。
  • 另一个不错的过滤器添加(如果非 Python 人员将处理您的模板)是这样的,对于您最常用的情况:def is_checkboxes(form_field_obj): return (form_field_obj.__class__.__name__ == "CheckboxSelectMultiple") ...然后您可以这样做 {% if field|is_checkboxes %}人们不会惊慌失措(......没有回报)
  • 修正我上一条评论中定义的函数:def is_checkboxes(form_field_obj): return (form_field_obj.field.widget.__class__.__name__ == "CheckboxSelectMultiple")
【解决方案2】:

跟进已接受的答案 - 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>

【讨论】:

  • field.field.widget 的目的是什么,而不是仅仅使用 field.widget
  • @Wipqozn 以我的经验field.widget 经常不产生任何结果 - 我不确定这一点,但也许只有在您手动设置时才会设置它。 field.field.widget 有效。
  • 查看文档中this section末尾的field.field信息
【解决方案3】:

根据 Oli 和 rinti 的回答:我用过这个,我认为它更简单一些:

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

过滤代码:

from django import template
register = template.Library()

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

【讨论】:

    【解决方案4】:

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

    【讨论】:

    • 我发现的唯一例外是 Textarea 小部件,据我所知,它没有 input_type 属性
    • 我创建了forms.Textarea 的子类,并添加了input_type = "textarea"
    【解决方案5】:

    也许值得向当代读者指出,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 模板标签。

    【讨论】:

      【解决方案6】:

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

      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 的调试器,您可以查看所有可用的元数据,如果您需要除字段类型之外的其他内容。

      【讨论】:

        猜你喜欢
        • 2018-07-18
        • 2011-02-09
        • 1970-01-01
        • 2012-06-14
        • 1970-01-01
        • 2015-10-12
        • 2017-09-14
        • 2017-03-22
        • 1970-01-01
        相关资源
        最近更新 更多