logicOnAbstractions
logicOnAbstractions

Reputation: 2580

Saving an object with formset element AND making a copy with new related elements

I'm trying to do some kind of a mixte between a Create and an Update on an object that has foreign keys (managed as inline formset).

Updating the parent object in a form (as well as its related formset forms) works fine. I can also save a copy of that parent object as a new instance in the DB, that works fine. However I can't seem to figure out how to also make copy of the formset as new independant objects.

Basically, once all is said & done, I want:

I currently can modify Foo, create FooCopy, as well as modify bar_1 to bar_n... but cannot create bar_1_copy etc.

For instance:

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())

My understanding was since the formset before the 2nd save refers to a new instance, it should save them as new objects. However it doesn't appear to be saving anything (since the formset, even after the 2nd call to formset.save(), still refer to the original parent instance).

Any suggestions as to how I should go about saving independant formset objects that refer to the copy of the original parent?

Upvotes: 0

Views: 1068

Answers (1)

logicOnAbstractions
logicOnAbstractions

Reputation: 2580

Turns out inspecting the definition of BaseInlineFormset (django.forms.model.py line 891) reveals a convenient kwargs for this:

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):

Thus, I actually pass to form_valid() 2 formset in this case, in 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)

And then instead of the 2nd formset.save() in the question above, I instead od formset_copy.save().

Yeah.

Upvotes: 2

Related Questions