Django表单字段选择,添加属性

标签 django django-forms

PLANNING_CHOICES = (
    ('0',u'Every morning'),
    ('1',u'Every night'),
    ('2',u'Never'),
)

planning = forms.ChoiceField(required=True, choices = PLANNING_CHOICES)

有一个名为 Planning 的表单字段,我需要向选项添加标题属性,并最终呈现如下:

<select>
    <option value="0" title="bla1">Every morning</option>
    <option value="1" title="bla2">Every night</option>
    <option value="2" title="bla3">Never</option>
</select>

如何实现?

最佳答案

这是一个通用解决方案,允许在 Select 小部件、SelectMultiple 小部件以及 Select2 小部件中的选项中使用属性。

它已经在 Django 2.1 上进行了测试,并且也应该适用于其他版本(在评论中告诉我)。

from django.forms.widgets import Select, SelectMultiple

class SelectWOA(Select):
    """
    Select With Option Attributes:
        subclass of Django's Select widget that allows attributes in options, 
        like disabled="disabled", title="help text", class="some classes",
              style="background: color;"...

    Pass a dict instead of a string for its label:
        choices = [ ('value_1', 'label_1'),
                    ...
                    ('value_k', {'label': 'label_k', 'foo': 'bar', ...}),
                    ... ]
    The option k will be rendered as:
        <option value="value_k" foo="bar" ...>label_k</option>
    """

    def create_option(self, name, value, label, selected, index, 
                      subindex=None, attrs=None):
        if isinstance(label, dict):
            opt_attrs = label.copy()
            label = opt_attrs.pop('label')
        else: 
            opt_attrs = {}
        option_dict = super(SelectWOA, self).create_option(name, value, 
            label, selected, index, subindex=subindex, attrs=attrs)
        for key,val in opt_attrs.items():
            option_dict['attrs'][key] = val
        return option_dict

这是一个您可以在 forms.py 中尝试的示例:

choices = [('b', 'blue'),
           ('g', {'label': 'green', 'disabled': 'disabled'}),
           ('c', {'label': 'cyan', 
                  'title': 'Kind of violet',
                  'style': 'background: cyan;',
                 }),
           ('r', 'red'), ]

colors = forms.ChoiceField(
    label="Colors",
    choices=choices,
    widget=SelectWOA)

colors可以在 Django shell 中渲染字段来检查结果:

(myvenv) $ ./manage.py shell
>>> from myapp.forms import *
>>> choices = ...
>>> colors = ...
>>> colors.widget.render('mycolors','')
'''<select name="mycolors">
      <option value="b">blue</option>
      <option value="g" disabled="disabled">green</option>
      <option value="c" title="Kind of violet" style="background: cyan;">cyan</option>
      <option value="r">red</option>
 </select>'''

要允许多项选择,请添加以下内容:

class SelectMultipleWOA(SelectWOA, SelectMultiple):
    """ 
    SelectMultipleWOA widget works like SelectMultiple, with options attrs.
    See SelectWOA.
    """
    pass

colors = forms.MultipleChoiceField(
    label="Colors",
    choices=choices,
    widget=SelectMultipleWOA)

它将渲染<select name="mycolors" multiple>...<\select> .

您可以使用 SelectWOA 和 SelectMultipleWOA 来扩展 Select2 小部件:

from django_select2.forms import Select2Mixin

class Select2MultipleWidgetWOA(Select2Mixin, SelectMultipleWOA):
    """
    Select2 drop in widget for multiple select.
    Works just like Select2MultipleWidget but with options attrs.
    """
    pass

colors = forms.MultipleChoiceField(
    label="Colors",
    choices=choices,
    widget=Select2MultipleWidgetWOA(
        attrs={'data-placeholder': 'Any color',
               'data-close-on-select': 'false',
               'style': 'width:280px; height:36px;',
               'title': 'Type a word to filter the menu',}
    )
)

它将呈现如下内容:

'''<select name="mycolors" data-placeholder="Any color" 
    class="django-select2" data-minimum-input-length="0" multiple 
    style="width:280px; height:36px;" data-close-on-select="false" 
    data-allow-clear="false" title="Type a word to filter the menu">
       <option value="b">blue</option>
       <option value="g" disabled="disabled">green</option>
       <option value="c" title="Kind of violet" style="background: cyan;">cyan</option>
       <option value="r">red</option>
    </select>'''

关于Django表单字段选择,添加属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5089396/

相关文章:

django - 使用 RequireJS 构建大型 JavaScript 代码

python - 我如何保持干燥?

python - 如何测试 ModelForm save() 方法保存模型中的更改?

Django HttpResponseRedirect 将变量传递给模板并读取它

python - Django 排除列表中*每个*项目的查询集 __in

python - Django(grappelli): how add my own css to all the pages or how to extend admin's base. html?

python - mysqldb 构建错误

django - 使用 django 模型表单中的现有数据填充 CheckboxSelectMultiple

django - 在处理之前更改 Django 表单数据

python - Django admin 中的自定义验证