首页 > 解决方案 > 使用 formset 元素保存对象并使用新的相关元素制作副本

问题描述

我正在尝试在具有外键(作为内联表单集管理)的对象上在 Create 和 Update 之间进行某种混合。

更新表单中的父对象(及其相关的表单集表单)可以正常工作。我还可以将该父对象的副本保存为数据库中的新实例,效果很好。但是我似乎无法弄清楚如何将表单集的副本也制作为新的独立对象。

基本上,一旦一切都说完了,我想要:

我目前可以修改 Foo,创建 FooCopy,以及将 bar_1 修改为 bar_n... 但无法创建 bar_1_copy 等。

例如:

class SoumissionUpdateView(LoginRequiredMixin, SideBarMixin, UpdateView):
    def form_valid(self, form, formset):
        # that saves any modification to the initial object, as well as the elements in the formset
        self.object = form.save()
        formset.instance = self.object
        formset.save()

        # this saves the parent object as a new instance. However no new formset objects are created in the db.
        self.object.pk = None
        self.object.save()
        formset.instance = self.object
        formset.save()                          # since those should be 2 different sets of instance in db
        return HttpResponseRedirect(self.get_success_url())

我的理解是因为第二次保存之前的表单集是指一个新实例,它应该将它们保存为新对象。但是它似乎没有保存任何东西(因为 formset,即使在第二次调用 formset.save() 之后,仍然引用原始父实例)。

关于我应该如何保存引用原始父级副本的独立表单集对象的任何建议?

标签: djangoinline-formset

解决方案


结果检查 BaseInlineFormset 的定义(django.forms.model.py 第 891 行)揭示了一个方便的 kwargs:

class BaseInlineFormSet(BaseModelFormSet):
    """A formset for child objects related to a parent."""
    def __init__(self, data=None, files=None, instance=None,
                 save_as_new=False, prefix=None, queryset=None, **kwargs):

因此,在这种情况下,我实际上传递给 form_valid() 2 formset,在 def post() 中:

def post(self, request, *args, **kwargs):
    self.object = self.get_object()
    form = self.get_form(self.get_form_class())
    formset = DetSoumFormset(self.request.POST, instance=self.object)
    formset_copy = DetSoumFormset(self.request.POST, instance=self.object, save_as_new=True)
    if form.is_valid() and formset.is_valid() and formset_copy.is_valid():
        return self.form_valid(form, formset, formset_copy)

然后不是上面问题中的第二个 formset.save(),而是 od formset_copy.save()。

是的。


推荐阅读