在django表单字段中向<option>
标记添加属性时,有一个很好的解释here。但这只适用于Select
widget。我想对SelectMultiple
widget执行相同操作。
在创建Select
表单字段SelectMultiple
时,我尝试了以下(子类MySelectMultiple
和Model
以及引用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
以使表单字段呈现为多选小部件 - 但是当保存表单时,只保存一个值(不是多个值)!
如何将表单呈现为多选字段并保存所有选定的值?谢谢。
答案 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