我有一个Django ModelForm,它通过一个模型来公开一个对应于多对多关系的多选字段,该模型将order
选择(文档列表)作为额外属性。在前端,该字段显示为两个与admin中类似的多个选择字段,一个列出可用选项,另一个列出所选元素。
表单可以使用正确的元素选择进行保存,但它们始终按原始选择顺序排列,而不是选择顺序。浏览器以正确的顺序发送选择,但form.cleaned_data['documents']
中的顺序始终是原始顺序的顺序。
如何使MultipleChoiceField尊重所选元素的顺序?
感谢。
答案 0 :(得分:5)
没有简单的方法。您需要覆盖clean
的{{1}}方法,或者如您在评论中提到的那样,使用getlist手动重新排序。这可能取决于您需要在代码中执行的频率。
MultipleChoiceField
clean
方法会通过像这样的MultipleChoiceField
运算符过滤对象列表来创建您正在接收的QuerySet
,因此订单由数据库:
IN
您可以继承qs = self.queryset.filter(**{'%s__in' % key: value})
:
ModelMultipleChoiceField
缺点是返回的值不再是class OrderedModelMultipleChoiceField(ModelMultipleChoiceField):
def clean(self, value):
qs = super(OrderedModelMultipleChoiceField, self).clean(value)
return sorted(qs, lambda a,b: sorted(qs, key=lambda x:value.index(x.pk)))
,而是普通列表。
答案 1 :(得分:0)
要在覆盖clean方法时返回有序的QuerySet,您也可以这样做:
with a as (
select a.col1, a.col2, a.col3, a.col4 from data
)
select a.col1, a.col2, a.col3, a.col4
from a
union all
select NULL, NULL,
sum(case when a.col2 = 'BBB' then a.col3
when a.col2 = 'CCC' then - a.col3
end),
sum(case when a.col2 = 'BBB' then a.col4
when a.col2 = 'CCC' then - a.col4
end)
from a;
答案 2 :(得分:0)
我通过Widget做到了。它的好处是,它将以不同的语言正确排序:
class SortedSelectMultiple(SelectMultiple):
def render_options(self, selected_choices):
self.choices = sorted(self.choices)
self.choices.sort(key=lambda x: x[1])
return super(SortedSelectMultiple, self).render_options(selected_choices)