将Django从1.9迁移到1.11:MultiValueField和MultiWidget行为出现问题 [英] Migrating Django from 1.9 to 1.11: trouble with MultiValueField and MultiWidget behaviour
问题描述
以下代码可以在Django 1.9中正常工作:
Here is a code that works as expected in 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
。 数据列表
始终是仅包含 False
的列表。 从未调用过解压缩
方法。
With Django 1.11, it no more works, the ValidationError
is always raised. The datalist
is always a list containing only False
. The decompress
method is never called.
我试图实现 value_from_datadict
方法非常老的帖子中建议,但没有成功。
I tried to implement a value_from_datadict
method as suggested in very old posts, but no success.
我看一下Djando代码,似乎是Django不喜欢将字段的结果( compress
的返回值)作为列表,所以我尝试将其转换为字符串(以逗号连接的值)。
I take a look to Djando code and it seems that Django does not like the result of the field (the return value of compress
) to be a list, so I tried to transform it into a string (as comma joined values). But the behaviour remains the same.
有什么想法吗?
编辑:
查看HTML源代码,看来子控件未正确呈现:它们都具有相同的名称,并且没有id。假设字段名称为 Valeurs
:
在Django 1.9中,HTML为:
In Django 1.9, the HTML is:
<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为:
In Django 1.11, the HTML is:
<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
正确,写得非常相似。我真的不明白问题出在哪里。
I have others MultiValueField/MultiWidget
that work correctly, written very similarly. I really don't understand where is the problem.
推荐答案
此处是发行说明所说的
删除了Widget.format_output()方法。改用自定义窗口小部件模板。
The Widget.format_output() method is removed. Use a custom widget template instead.
https://docs.djangoproject.com/zh-CN/1.11/releases/1.11/#由于基于模板的小部件渲染的引入而发生的变化
这篇关于将Django从1.9迁移到1.11:MultiValueField和MultiWidget行为出现问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!