Olivier Pons
Olivier Pons

Reputation: 15796

Django: difference between is_valid and form_valid

I've created a form which is a forms.ModelForm. On the "view" side, I've created a view which is a generic.UpdateView.

In those 2 differents classes, I have is_valid() on one side, and form_valid() on the other side.

class ProfileForm(FormForceLocalizedDateFields):

    class Meta:
        model = Personne
        fields = ('sexe', 'statut', 'est_fumeur',
                  'est_physique', 'date_naissance')
        exclude = ('user', 'est_physique')

    # blabla fields declaration

    def is_valid(self):
        pass

and edit view:

class EditView(LoginRequiredMixin, generic.UpdateView):
    model = Personne
    template_name = 'my_home/profile/edit.html'
    form_class = ProfileForm
    success_url = reverse_lazy('my_home_index')

    # blabla get_initial() and get_object() and get_context_data()

    def form_valid(self, form):
        # username = form.cleaned_data['username']
        # Hack: redirect on same URL:
        # - if user refreshes, no form re-send
        # - if user goes back, no form re-send too, classical refresh
        site_web = u"{0}://{1}".format(
            self.request.scheme, self.request.META['HTTP_HOST']
        )
        return HttpResponseRedirect(u'{0}{1}'.format(
            site_web, self.request.META['PATH_INFO']
        ))

My form shows 3 fields of 3 different models :

Where should I create the code that update those fields, and why?

generic.UpdateView is supposed to help us when updating fields, but it seems that when you have fields not belonging to the model you edit, you have to write all the "update" by hand.

Upvotes: 4

Views: 1767

Answers (1)

Sayse
Sayse

Reputation: 43320

is_valid on the surface just tells you whether or not the form is valid, and thats the only job it should ever do..

From the source code:

def is_valid(self):

    """
    Returns True if the form has no errors. Otherwise, False. If errors are
    being ignored, returns False.
    """
    return self.is_bound and not self.errors

Underneath this, what it also does is (from docs)

run validation and return a boolean designating whether the data was valid:

The validation is ran because errors is a property that will call full_clean if the validation hasn't been called yet.

 @property
 def errors(self):

    "Returns an ErrorDict for the data provided for the form"
    if self._errors is None:
        self.full_clean()
    return self._errors

Where should I create the code that update those fields, and why?

In the form_valid method because by this point you've found out that your validation has verified that it is safe to update your model.

Upvotes: 4

Related Questions