Implementing this yourself often results in a lot of repeated boilerplate code
(see Using a form in a view). To help avoid
this, Django provides a collection of generic class-based views for form
processing.

frommyapp.formsimportContactFormfromdjango.views.generic.editimportFormViewclassContactView(FormView):template_name='contact.html'form_class=ContactFormsuccess_url='/thanks/'defform_valid(self,form):# This method is called when valid form data has been POSTed.# It should return an HttpResponse.form.send_email()returnsuper().form_valid(form)

We have to use reverse_lazy() here, not just
reverse() as the urls are not loaded when the file is imported.

The fields attribute works the same way as the fields attribute on the
inner Meta class on ModelForm. Unless you define the
form class in another way, the attribute is required and the view will raise
an ImproperlyConfigured exception if it’s not.

Here is a simple example showing how you might go about implementing a form that
works for AJAX requests as well as ‘normal’ form POSTs:

fromdjango.httpimportJsonResponsefromdjango.views.generic.editimportCreateViewfrommyapp.modelsimportAuthorclassAjaxableResponseMixin:""" Mixin to add AJAX support to a form. Must be used with an object-based FormView (e.g. CreateView) """defform_invalid(self,form):response=super().form_invalid(form)ifself.request.is_ajax():returnJsonResponse(form.errors,status=400)else:returnresponsedefform_valid(self,form):# We make sure to call the parent's form_valid() method because# it might do some processing (in the case of CreateView, it will# call form.save() for example).response=super().form_valid(form)ifself.request.is_ajax():data={'pk':self.object.pk,}returnJsonResponse(data)else:returnresponseclassAuthorCreate(AjaxableResponseMixin,CreateView):model=Authorfields=['name']