Django,给ManyToMany的表单集设置初始数据

4 投票
3 回答
4518 浏览
提问于 2025-04-16 13:10

我需要给一个包含ManyToMany字段的formset设置初始数据。

通常情况下,当我的formset中没有ManyToMany字段时,我是这样做的:

PersonFormSet = forms.formsets.formset_factory(NickName, can_delete=True)
init_data = [{'name':'Vasya pupkin','nick':'Vasya'}, 
             {'name':'Vasyapupkin','nick':'Petya'}]

nick_formset = PersonFormSet(initial=init_data)

但是现在我需要设置ManyToMany字段的初始数据,尝试了这样的方式:

NickNameFormSet = forms.formsets.formset_factory(NickName, can_delete=True)
init_data = [{'name': 'Vasya Pupkin',
              'nick': {'Vasya':'selected',
                       'Petya':'notselected'}}]

nick_formset = NickNameFormSet(initial=init_data)

但是这并没有成功。

我该如何将初始数据传递给Formset,以便它能像这样渲染我的控件:

<select multiple="multiple" name="person_set-0-nickname" id="id_person_set-0-nickname">
    <option value="1" selected="selected">Vasya</option>
    <option value="2">Petya</option>
</select>

注意:我只在使用Django的Forms和Formsets,并没有使用Django模型。其实我可以定义模型,但它是空的,我在使用NoSQL

3 个回答

0

像这样:

class CustomFormSet(BaseInlineFormSet):
    def __init__(self, *args, **kwargs):
        kwargs['initial'] = [
            {'foo_id': 1}
        ]
        super(CustomFormSet, self).__init__(*args, **kwargs)

foo_id的值取决于你在模型关系中选择的字段。

你还需要修改表单类中的has_changed方法,这样它才能知道初始值已经“改变”,在保存时会被考虑进去:

class CustomForm(forms.ModelForm):
    def has_changed(self):
        """
        Overriding this, as the initial data passed to the form does not get noticed,
        and so does not get saved, unless it actually changes
        """
        changed_data = super(starnpc_class, self).has_changed()
        return bool(self.initial or changed_data)
0

你可以用 __init__ 函数来提前填充一些初始数据。

这是我在解决类似问题时用的:

class MyUpdateForm(forms.ModelForm):

    def __init__(self, *args, **kwargs):
        super(MyUpdateForm, self).__init__(*args, **kwargs)
        self.initial['real_supplements'] = [s.pk for s in list(self.instance.plan_supplements.all())]

在我的例子中,不用 self.instance.plan_supplements.all(),你可以提供任何查询集(Queryset)。

1

你应该提供一个 pk 的列表作为你多对多关系的初始数据,而不是用 dict

可以看看 这个讨论,可能会对你有帮助。

撰写回答