这是一个在Django 1.9中按预期工作的代码:
class MultipleBooleanField(forms.MultiValueField):
def __init__(self, *args, **kwargs):
self.fieldnames = kwargs.pop('fields')
fields = [ forms.BooleanField(required=False) for x in self.fieldnames ]
super(MultipleBooleanField, self).__init__(fields=fields,
require_all_fields=False, *args, **kwargs)
self.widget = MultipleBooleanWidget(widgets=[ f.widget for f in fields ])
self.widget.fieldnames = self.fieldnames
def compress(self, datalist):
# return a list of the fieldnames, datalist is a list of booleans
print('compress datalist:', datalist)
if self.required and not any(datalist):
raise forms.ValidationError('You must choose at least one value')
return [ self.fieldnames[i] for i in range(len(datalist)) if datalist[i] ]
class MultipleBooleanWidget(forms.MultiWidget):
def render(self, name, value, attrs=None, renderer=None):
if not value:
value = [ False for x in self.fieldnames ]
rendered_widgets = [ x.render(name, value[i]) for i,x in enumerate(self.widgets) ]
items = [ '%s %s' % (rendered_widgets[i], f)
for (i,f) in enumerate(self.fieldnames) ]
return ' '.join(items)
def decompress(self, value):
# return a list of booleans, value is a list of fieldnames
print('decompress value:', value)
if not value:
return [ False for x in self.fieldnames ]
return [ x in value for x in self.fieldnames ]
使用Django 1.11,它不再有用,ValidationError
总是被提升。 datalist
始终是仅包含False
的列表。 永远不会调用decompress
方法。
我尝试按照旧帖子中的建议实施value_from_datadict
方法,但没有成功。
我看看Djando代码,似乎Django不喜欢字段的结果(compress
的返回值)作为列表,所以我试图将它转换为字符串(如逗号加入了值)。但行为仍然相同。
有什么想法吗?
修改
查看HTML源代码,看起来子窗口小部件未正确呈现:它们都具有相同的名称,并且没有id。假设字段名称为Valeurs
:
在Django 1.9中,HTML是:
<tr><th><label for="id_Valeurs_0">Valeurs :</label></th><td><input checked="checked" id="id_Valeurs_0" name="Valeurs_0" type="checkbox" /> Part du total com <input checked="checked" id="id_Valeurs_1" name="Valeurs_1" type="checkbox" /> Part du total Qté <input checked="checked" id="id_Valeurs_2" name="Valeurs_2" type="checkbox" /> ...
在Django 1.11中,HTML是:
<tr><th><label for="id_Valeurs_0">Valeurs :</label></th><td><input type="checkbox" name="Valeurs" checked /> Part du total com <input type="checkbox" name="Valeurs" checked /> Part du total Qté <input type="checkbox" name="Valeurs" checked />
我让其他MultiValueField/MultiWidget
工作正常,写得非常相似。我真的不明白问题出在哪里。
答案 0 :(得分:2)
以下是发行说明所说的内容
删除了Widget.format_output()方法。改为使用自定义小部件模板。
答案 1 :(得分:1)
我发现了问题:它来自rendered_widgets
方法中render
的计算,必须是:
rendered_widgets = [ x.render('%s_%d' % (name,i), value[i]) for i,x in enumerate(self.widgets) ]
使用该解决方案,呈现的HTML具有正确的名称,但仍然没有id。但它确实有效。
我不明白为什么django团队删除了MultiWidget的format_output
方法:它很有用,简单,高级。必须处理render
是痛苦的,但也许我错过了一些东西......