在表单字段中添加额外信息并在渲染django模板时使用它

时间:2012-03-07 13:56:41

标签: python django forms django-templates twitter-bootstrap

我想为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原则的误解(网站外观应该是模板,而不是表格)......

3 个答案:

答案 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的表示。