Django为SelectMultiple <option>标记添加属性

时间:2017-04-20 15:44:50

标签: python django

在django表单字段中向<option>标记添加属性时,有一个很好的解释here。但这只适用于Select widget。我想对SelectMultiple widget执行相同操作。

在创建Select表单字段SelectMultiple时,我尝试了以下(子类MySelectMultipleModel以及引用employees

class MySelect(forms.Select):

    def __init__(self, *args, **kwargs):
            super(MySelect, self).__init__(*args, **kwargs)

    def render_option(self, selected_choices, option_value, option_label):
        # original forms.Select code #
        return u'<option custom_attribute="foo">...</option>'

class MySelectMultiple(MySelect):
    def __init__(self, *args, **kwargs):
        super(MySelectMultiple, self).__init__(*args, **kwargs) 

employees = forms.ModelMultipleChoiceField(
                    widget=MySelectMultiple(attrs={}),
                    queryset=Employee.objects.all(),
                )

但渲染的表单仍然显示为Select窗口小部件,而不是SelectMultiple窗口小部件。

我可以向attrs={'multiple':'multiple'}提供MySelectMultiple以使表单字段呈现为多选小部件 - 但是当保存表单时,只保存一个值(不是多个值)!

如何将表单呈现为多选字段并保存所有选定的值?谢谢。

3 个答案:

答案 0 :(得分:2)

您的选择倍数应该继承自SelectMultiple而不是Select

class MySelectMultiple(SelectMultiple):
    def render_option(self, selected_choices, option_value, option_label):
        # original forms.Select code #
        return u'<option custom_attribute="foo">...</option>'

看起来您的__init__方法不是必需的,因为它只是调用super()

答案 1 :(得分:0)

好吧,想通了:使用:

class MySelectMultiple(MySelect):
    def __init__(self, *args, **kwargs):
        super(MySelectMultiple, self).__init__(*args, **kwargs) 

我仍在使用django原生Select,但只是将其称为MySelectMultiple。我需要导入SelectMultiple rest

所以,而不是:

class MySelectMultiple(MySelect):
    def __init__(self, *args, **kwargs):
        super(MySelectMultiple, self).__init__(*args, **kwargs) 

该类需要完整(复制/粘贴SelectMultiple的原生django代码):

class MySelectMultiple(MySelect):
    allow_multiple_selected = True

    def __init__(self, *args, **kwargs):
        super(MySelectMultiple, self).__init__(*args, **kwargs)


    def render(self, name, value, attrs=None, choices=()):
        if value is None:
            value = []
        final_attrs = self.build_attrs(attrs, name=name)
        output = [format_html('<select multiple="multiple"{0}>', forms.utils.flatatt(final_attrs))]
        options = self.render_options(choices, value)
        if options:
            output.append(options)
        output.append('</select>')
        return mark_safe('\n'.join(output))

    def value_from_datadict(self, data, files, name):
        if isinstance(data, (MultiValueDict, MergeDict)):
            return data.getlist(name)
        return data.get(name, None)

答案 2 :(得分:0)

SelectMultiple从Select继承,您只需要重写create_option方法即可获得相同的结果:

class MySelectMultiple(forms.SelectMultiple):
    def create_option(self, name, value, *args, **kwargs):
        option = super().create_option(name, value, *args, **kwargs)
        if value:
            instance = self.choices.queryset.get(pk=value)  # get instance
            option['attrs']['custom_attr'] = instance.field_name  # set option attribute
        return option