Using form.save(commit=False) in a Class Based View

UPDATE: I found a better way to do this.  See this post.

In this example, I once again hadn’t used a generic view for this create function, since I needed to add a value that is not in the form to the new object before the save.

    if form.is_valid():
        new_rec = form.save(commit=False)
        new_rec.institution = institution
        new_rec.save()
        return HttpResponseRedirect(reverse('cat_list'))

The value for institution comes from the user’s session area. The above is the accepted pattern to add the data to the object.

So how can we do this in a class based view?

An override of form_valid() in the class will handle this case.

    def form_valid(self, form):
        self.object = form.save(commit=False)
        self.object.institution = self.kwargs['institution']
        self.object.save()
        return HttpResponseRedirect(self.get_success_url())

(Putting the institution value in kwargs is the subject for another post. One could also use an object variable.)

UPDATE: I found a better way to do this.  See this post.

The reader who just wants to know how to do this can stop here. However….

Is this the best way to do this?

I’m not very skilled in the art of overriding methods, so I am a little concerned about the forward compatibility of this solution.
Let’s first see the upstream definitions of this method.
The method is defined in ModelFormMixin as follows:

    def form_valid(self, form):
        self.object = form.save()
        return super(ModelFormMixin, self).form_valid(form)

And above that we find a simpler method in FormMixin:

    def form_valid(self, form):
        return HttpResponseRedirect(self.get_success_url())

I like how the ModelFormMixin method is able to refer back to the original using the super function, but I don’t know how I can jump over the immediate ancestor to call back the original method. Is this possible? Does it matter?

I am slightly concerned that changes to the method in FormMixin that may come along in future versions may be overlooked with this solution. Sure, I have to check these things during an upgrade anyway, but I would like to perform this as “correctly” as possible.

Please leave your suggestions, thoughts and comments below.

UPDATE: I found a better way to do this.  See this post.

Comments are closed.