我正在遍历表单的字段,对于某些字段,我想要稍微不同的布局,需要更改HTML。
为了准确地做到这一点,我只需要知道小部件类型。它的类名或类似的东西。在标准的python中,这很容易! field.field.widget.__class__.__name__
不幸的是,您不允许访问模板中的下划线变量。 大!
您可以测试field.field.widget.input_type
,但这仅适用于文字/密码<input ../>
类型。我需要更多的解决方案。
对我而言,无论它看起来多么困难,最适合在模板级别执行此操作。我已经将处理字段HTML的代码外包给了一个单独的模板,该模板包含在字段循环中。这意味着它在ModelForm
和标准Form
之间是一致的(如果我写了一个中间的Form类,则不会出现这种情况)。
如果您能看到一种不需要我编辑20多种形式的通用方法,请告诉我!
答案 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_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
模板标记。
答案 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调试器查看所有可用的元数据。