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

Lab*_*che 3 python forms django 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
Run Code Online (Sandbox Code Playgroud)

我在模板中渲染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 %}
Run Code Online (Sandbox Code Playgroud)

我无法使用小部件的attrs,因为我想在渲染的输入标记之外使用属性信息.

我应该创建一个自定义字段,为我使用的所有字段编写自定义渲染器,还是有一个我错过的更简单的解决方案?


编辑:到目前为止,我的解决方案是:(简化版)主模板:

<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" %}
 ...
Run Code Online (Sandbox Code Playgroud)

在form_field.html中,我使用Twitter的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>
Run Code Online (Sandbox Code Playgroud)

我想要的只是简化主模板,使用循环而不是枚举所有字段,这很容易出错.所以我想将"icon-home"属性从模板移动到表单定义,将所有属性放在同一个地方(特定小部件attrs已经在表单中).理想情况下,在主模板中我会:

{% for item in form.visible_fields %}
  {% include 'form_field.html' %}
{% endfor %}
Run Code Online (Sandbox Code Playgroud)

我理解它可以被视为对Django原则的误解(网站外观应该是模板,而不是形式)......

tam*_*are 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)
Run Code Online (Sandbox Code Playgroud)

您需要为您使用的每种表单字段类型提供自定义字段类型.以下是IntegerField的完成方式.您的自定义字段类需要从原始的django表单字段类(在本例中为IntegerField)和IconName继承.

class CustomCharField(CharField, IconName):
    pass
Run Code Online (Sandbox Code Playgroud)

定义表单所需的所有自定义表单字段类型后,使用它们更新表单.接下来,您需要初始化icon_name表单中的每个表单字段__init__():

def __init__(self, *args, **kwargs):
    super(forms.Form, self).__init__(*args, **kwargs)
    self.fields['integer'].icon_name = 'icon-home'
    ...
Run Code Online (Sandbox Code Playgroud)

在您的模板中,您可以:

{% 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 %}
Run Code Online (Sandbox Code Playgroud)

我自己没试过,但它应该有效(假设我理解正确)