Bryson
Bryson

Reputation: 1266

Is my recommendation of using super() incorrect?

I have seen many answers here where the recommended course of action in overloading a given default method from Django is to simply copy the code from that original method, and include it with your modifications in your overloaded version of said method.

For example, an answer given:

class MyUpdateView(UpdateView):
    def form_valid(self, form):
        self.object = form.save(commit=False)
        self.object.user = self.request.user
        self.object.save()
        return HttpResponseRedirect(self.get_success_url())

   # the default implementation of form_valid is...
   # def form_valid(self, form):
   #     self.object = form.save()
   #     return HttpResponseRedirect(self.get_success_url())

So the two lines that the answerer says are the default form_valid are not actually the default code, but they are the code that gets executed through inheritance. Regardless, their answer removed the execution of any Django code forward of form_valid and replaces it with a direct HttpResponseRedirect() call.

The way I would write this method is as follows:

class MyUpdateView(UpdateView):
    def form_valid(self, form):
        self.object = form.save(commit=False)
        self.object.user = self.request.user
        return super(MyUpdateView, self).form_valid(form)

Django's own code follows this convention. Taken from views/generic/edit.py line 111:

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

This is the true default version of form_valid that the answerer of this other question is referring to.

So the nut of this question: Is there any reason I shouldn't be using super() in this way in my projects, in the same way that Django's code does it internally? The advantage, to me, is that if Django were to ever update the way that these views work internally, chances are much better that my code — which simply extends and continues to execute Django's — will remain compatible. In addition, it keeps me from re-writing code that is already written by simply executing the existing code with modifications. Is this not one of super()'s intended uses?

Upvotes: 2

Views: 457

Answers (1)

DrTyrsa
DrTyrsa

Reputation: 31951

Yes, there is a reason.

Let's replace your super call with actual Django method.

class MyUpdateView(UpdateView):
    def form_valid(self, form):
        self.object = form.save(commit=False)
        self.object.user = self.request.user
        self.object = form.save() # oops, we redefined self.object, user won't be saved
        return HttpResponseRedirect(self.get_success_url())

So this won't work. Of course using super is always DRY'er and better, but it's not always possible.

In your example from Django source it is another situation: the child does saving and the parent does redirection. No "overlaps" here.

Upvotes: 3

Related Questions