form_valid()

I have a view based on CreateView with the following form_valid() code:

def form_valid(self, form):
        form.instance.node_id = self.request.user.node_id
        return super().form_valid(form)

and a view based on FormView with this code:

def form_valid(self, form):
        form.instance.node_id = self.request.user.node_id
        form.save()
        return super().form_valid(form)

I don’t understand why I need form.save() in case of a FormView.

Kind regards,

Johanna

The CreateView, is by definition, intended to create an instance of a model. It inherits from (among others) the ModelFormMixin.

The FormView is more generic than that. Not all forms are associated directly with models. It exists to allow for general form handling. If you’re using a ModelForm with FormView, then yes, the responsibility is yours to save the model being edited.

There is another choice. Django provides the UpdateView which is an edit-view associated with a Model form.

When you have questions like this about these Django generic CBVs, the best sources of information are the docs at:

If you’re going to build your systems around these CBVs, you will find it worth your time to dig underneath the covers to understand how they work and how they’re put together.

Yes, I understand they’re complex - and frequently a bit opaque, and yes, there are alternatives (Django Vanilla Views). And, they are still being (occasionally) changed (e.g. DeleteView changes). But this is one of those areas where you’re probably best-served by that effort.

Hi Ken,

Thanks for your reply. I got it.

I re-read the documentation on: Generic editing views | Django documentation | Django and had a look at the method flowcharts

Based on the example I wrote this code:

class OrganisationFormView(LoginRequiredMixin, PermissionRequiredMixin, FormView):
    form_class = forms.OrganisationForm
    template_name = 'generic/form.html'
    succes_url = reverse_lazy('node-index')

    def form_valid(self, form):
        form.instance.node_id = self.request.user.node_id
        form.save()
        return super().form_valid(form)

Although I provide a succes_url I get the following error:

Exception Type:	ImproperlyConfigured
Exception Value:	No URL to redirect to. Provide a success_url.

At Classy Class-Based Views they document form_valid as follows:

def form_valid(self, form):
    """If the form is valid, redirect to the supplied URL."""
    return HttpResponseRedirect(self.get_success_url())

I don’t understand why the return values are different.

Kind regards,

Johanna

Should be success_url, not succes_url.

Can you clarify? What return values are you saying are different?

Side note: Having both of these is redundant. All Permission tests require a valid logon account, the AnonymousUser will fail all permission tests. Therefore, you don’t need to have a separate test for being logged in.

Thanks for saving my evening. In my native language we write success with one ‘s’

I meant: return super().form_valid(form) versus return HttpResponseRedirect(self.get_success_url())

Thanks for the comment on the RequiredMixin, I’ll remove LoginRequiredMixin.

If I want to update another object like:

node = models.Nodes.objects.get(id=self.request.user.node_id)
node.full_name = form.instance.full_name
node.save()

Should I put that in the form_valid method or somewhere else?

Kind regards,

Johanna

Would you consider me rude if I were you ask you what your native language is? (Your English is superb, I would have never guessed otherwise.)

So let’s break this down into what’s happening here.

The return statement returns a value.

So the line return HttpResponseRedirect(self.get_success_url()) effectively does the following, but in one line instead of three:

success_url = self.get_success_url()
response = HttpResponseRedirect(success_url)
return response

Now, let’s make this a function and call it get_response:

def get_response():
    success_url = self.get_success_url()
    response = HttpResponseRedirect(success_url)
    return response

Now, the reference to super() is a reference to the parent class of the current object. In context then, super().form_valid(form) is a reference to the first instance of the form_valid method in the Method Resolution Order (MRO) in the parent class of this specific view. What it does then in this case is effectively the same as:
return get_response()

Effectively what’s happening is that your form_valid method isn’t returning a value itself - it’s calling the parent class to get the value to be returned to the calling function.

The form_valid method would be the right place for that. That’s the function that is called if the form passes all the appropriate validation tests. (That’s assuming you only want that node object updated if the form is valid. If you want node to be updated regardless of the validity of the form, you would choose a different location to do this.)

Thank you. No, not at all. My native language is Dutch, which is a very small language, hence learning English as a second language is almost a necessity.

This break down is very helpful. Maybe it’s just me but I miss this kind of breakdowns in the documentation and books I read.

Yes, that’s exactly what I want.

Kind regards,

Johanna