我想为django表单的某些字段添加额外的信息,并在模板中使用它来添加一些额外的html标记
我有一个django形式,如:
class MyForm(forms.Form):
integer = forms.IntegerField(
help_text='Please enter your favorite integer number',
label='Favorite integer',
widget=forms.TextInput(attrs={'class':'input-xlarge'}))
decimal = forms.DecimalField(
min_value=Decimal('0.0001'),
decimal_places=4,
help_text='Please enter your favorite decimal number',
label='Favorite decimal',
widget=forms.TextInput(attrs={'class':'input-xlarge'}))
==> here I would like to say: decimal will have a new property
我在模板中渲染MyForm,在每个字段上使用循环:
{% for item in form.visible_fields %}
==> here I would like to test if item has that property to add some html tags
{{ item }}
{% endfor %}
我不能使用小部件的attrs,因为我想在渲染的输入标记之外使用属性信息。
我应该create a custom field,为我使用的所有字段编写自定义渲染器,还是有一个我错过的更简单的解决方案?
编辑:到目前为止我的解决方案是:(简化版) 主要模板:
<form action="/somewhere/" method="post">{% csrf_token %}
{% include 'form_field.html' with item=form.integer icon="icon-home" %}
{% include 'form_field.html' with item=form.decimal icon="icon-list-alt" %}
{% include 'form_field.html' with item=form.another icon="icon-signal" %}
{% include 'form_field.html' with item=form.again icon="icon-time" %}
...
在form_field.html中,我使用Twitter's Bootstrap input-prepend div呈现字段:
<div class="control-group">
<label class="control-label" for="{{ item.name }}">{{ item.label }}</label>
<div class="controls">
{% if icon %}
<div class="input-prepend">
<span class="add-on"><i class="{{ icon }}"></i></span>
{% endif %}
{{ item }}
<p class="help-block">{{ item.help_text }}</p>
{% if icon %}
</div>
{% endif %}
</div>
</div>
我想要的只是简化主模板,使用循环而不是枚举所有字段,这很容易出错。所以我想将“icon-home”属性从模板移动到表单定义,将所有属性放在同一个地方(特定小部件attrs已经在表单中)。 理想情况下,在主模板中我会:
{% for item in form.visible_fields %}
{% include 'form_field.html' %}
{% endfor %}
我理解它可以被视为对Django原则的误解(网站外观应该是模板,而不是表格)......
答案 0 :(得分:5)
自定义表单字段 + 多重继承 + 存储图标类名称的类
首先,让我们定义一个捕获图标类名的类。我们称之为 IconName :
class IconName(object):
def get_icon_name(self):
return self._icon_name
def set_icon_name(self, value):
self._icon_name = value
icon_name = property(get_icon_name, set_icon_name)
您需要为您使用的每种表单字段类型提供自定义字段类型。以下是IntegerField的完成方式。您的自定义字段类需要从原始的django表单字段类(在本例中为IntegerField)和 IconName 类继承。
class CustomCharField(CharField, IconName):
pass
在定义了表单所需的所有自定义表单字段类型后,请使用它们更新表单。接下来,您需要为表单icon_name
中的每个表单字段初始化__init__()
:
def __init__(self, *args, **kwargs):
super(forms.Form, self).__init__(*args, **kwargs)
self.fields['integer'].icon_name = 'icon-home'
...
在您的模板中,您可以执行以下操作:
{% for item in form.visible_fields %}
<div class="control-group">
<label class="control-label" for="{{ item.name }}">{{ item.label }}</label>
<div class="controls">
{% if item.field.icon_name %}
<div class="input-prepend">
<span class="add-on"><i class="{{ item.field.icon_name }}"></i></span>
{% endif %}
{{ item }}
<p class="help-block">{{ item.help_text }}</p>
{% if item.field.icon_name %}
</div>
{% endif %}
</div>
</div>
{% endfor %}
我自己没有尝试过,但它应该有效(假设我理解正确)
答案 1 :(得分:0)
警告:我刚开始使用Python和Django。
看看这是否有助于您入门:
class MyCustomTextInput(forms.widgets.TextInput):
def render(self, name, value, attrs=None):
original_html = super(MyCustomRender,self).render(name, value, attrs)
icon_html = "<img src='/img.png' />"
return "%s%s" % (icon_html,original_html)
class MyForm(ModelForm):
myfield = MyCustomTextInput()
我相信这会产生类似于:
的输出<img src='/img.png' /><input type="text" ... />
查看https://github.com/django/django/blob/master/django/forms/widgets.py
答案 2 :(得分:-1)
Django默认带有一个简单的渲染器。
来自django的documentation:
<form action="/contact/" method="post">{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="Submit" />
</form>
至于自定义图像的使用,如果您的表单是动态的,Javascript将是一个解决方案。表单模型不是,因为它只是一种旨在有效创建fomrs的表示。