Django:表单集CBV上的保存(commit=False)触发了定制模型的保存()操作

t98cgbkg  于 2023-11-20  发布在  Go
关注(0)|答案(1)|浏览(83)

我正在使用CBVViewView向用户显示几个带有表单集的页面。
当一个给定的formset/mysql View背后的模型是一个公共的模型时(稍后会更清楚),在视图上使用以下逻辑一切都可以正常工作:

class Create(CreateView):
    ...

    def form_valid(self, formset):
        instances = formset.save(commit=False)
        for instance in instances:
            instance.user = self.request.user
            instance.save()

        return super(Create, self).form_valid(formset)

字符串
然而,在其中一个模型上,我必须向模型保存()方法添加额外的操作。也就是说,我需要在保存父对象时创建子对象。类似于:

class Parent(models.Model):
    ...
        
    def save(self, *args, **kwargs):
        super().save(*args, **kwargs)
        self.child_set.create(...., *args, **kwargs)


在这个特殊的例子中,子对象被创建了两次,我相信formset.save(commit=False)是罪魁祸首。
我尝试将child_set.create()替换为

child = Child(...parameters, parent=self)
        child.save(*args, **kwargs)


但结果是一样的。我怎么才能避免呢?

d7v8vwbk

d7v8vwbk1#

CreateView[Django-doc]的**.form_valid(…)**方法[Django-doc]将在form上调用.save(),这将调用新一轮保存所有对象。

您可以设置示例的.user,然后让CreateView保存这些示例。这意味着您可以将其实现为:

class Create(CreateView):
    # …

    def form_valid(self, formset):
        instances = formset.save(commit=False)
        for instance in instances:
            instance.user = self.request.user
            # no instance.save()
        #                  ↓ this will save the instances
        return super().form_valid(formset)

字符串
也就是说,使用**.get_or_create(…)[Django-doc]可能比使用.create(…)**[Django-doc]更好,因为现在您将在每次保存Parent对象时创建一个Child对象,这可能不是预期的效果。

相关问题