I’m using CBV CreateView to display a couple of pages with formsets to the user.
When the model behind a given formset/CreateView is a common one (it will became clearer later), everything works fine using the following logic on the 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)
However, on one of the models, I had to add extra actions to the model save() method. Namely, I need to create child objects when the parents are saved. Something like:
class Parent(models.Model): ... def save(self, *args, **kwargs): super().save(*args, **kwargs) self.child_set.create(...., *args, **kwargs)
In this particular case, the child object is being created twice and I believe that the formset.save(commit=False) is the culprit.
I tried replacing the child_set.create() for
child = Child(...parameters, parent=self) child.save(*args, **kwargs)
But it yields the same result. How can I prevent that?
You can set the
.user of the instances, and then let the
CreateView save these instances. This thus means that you implement this as:
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)
That being said, it might be better to work with a
.get_or_create(…) [Django-doc] over a
.create(…) [Django-doc], since now you will create a
Child object each time you save the
Parent object, which is likely not the intended effect.