Django:表单集 CBV 上的保存(commit=False)正在触发自定义模型保存()操作

Django: save(commit=False) on formset CBV is triggering customized model save() actions

我正在使用 CBV CreateView 向用户显示几个带有表单集的页面。

当给定 formset/CreateView 背后的模型是普通模型时(稍后会变得更清楚),在视图上使用以下逻辑一切正常:

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)

但是,在其中一个模型上,我不得不向模型的 save() 方法添加额外的操作。即,我需要在保存 parents 时创建 child object。类似于:

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

在这种特殊情况下,child object 被创建了两次,我认为 formset.save(commit=False) 是罪魁祸首。

我尝试将 child_set.create() 替换为

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

但它产生了相同的结果。我怎样才能避免这种情况?

.form_valid(…) method [Django-doc] of a CreateView [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
            # <strong>no</strong> instance.save()
        #                  ↓ this will save the instances
        return super().form_valid(formset)

也就是说,使用 .get_or_create(…) [Django-doc] over a .create(…) [Django-doc] 可能会更好,因为现在您将创建一个 Child 对象 each Parent 对象,这可能不是预期的效果。