Django 1.8 official document translation: 3-4-3 use class based view to process forms

Time:2021-9-17

Working with forms using class based views

The processing of forms usually has three steps:

  • Initial get (blank or pre filled form)

  • Post with illegal data (usually redisplays forms and error messages)

  • Post with legal data (process data and redirect)

Implementing these functions yourself often leads to a lot of duplicate sample code (see using forms in views). To avoid this, Django provides a series of general class based views for form processing.

Basic form

According to a simple contact form:

#forms.py

from django import forms

class ContactForm(forms.Form):
    name = forms.CharField()
    message = forms.CharField(widget=forms.Textarea)

    def send_email(self):
        # send email using the self.cleaned_data dictionary
        pass

have access toFormViewTo construct its view:

#views.py

from myapp.forms import ContactForm
from django.views.generic.edit import FormView

class ContactView(FormView):
    template_name = 'contact.html'
    form_class = ContactForm
    success_url = '/thanks/'

    def form_valid(self, form):
        # This method is called when valid form data has been POSTed.
        # It should return an HttpResponse.
        form.send_email()
        return super(ContactView, self).form_valid(form)

Note:

  • FormViewinheritTemplateResponseMixinSo you can use it heretemplate_name

  • form_valid()The default implementation of simply redirects tosuccess_url

Form for model

The common view is that the model really shines when it works together. These general views will automatically create a modelform as long as they know which model class to use:

  • If givenmodelProperty, the model class is used.

  • Ifget_object()If an object is returned, the class of the object is used.

  • If givenqueryset, the model of the query set is used.

The model form provides aform_valid()It automatically saves the model. If you have special needs, you can cover it; See the example below.

You don’t even have toCreateViewandUpdateViewprovidesuccess_url——If they exist, they use the of the model objectget_absolute_url()

If you want to use a customModelForm(for example, add additional validation), simply set it on your viewform_class

notes

When specifying a custom form class, you must specify a model, even ifform_classIt could be aModelForm

First we need to addget_absolute_url()To ourAuthorIn class:

#models.py

from django.core.urlresolvers import reverse
from django.db import models

class Author(models.Model):
    name = models.CharField(max_length=200)

    def get_absolute_url(self):
        return reverse('author-detail', kwargs={'pk': self.pk})

Then we can useCreateViewMachine partners to do practical work. Notice how we configure the generic class based view here; We didn’t write any logic ourselves:

#views.py

from django.views.generic.edit import CreateView, UpdateView, DeleteView
from django.core.urlresolvers import reverse_lazy
from myapp.models import Author

class AuthorCreate(CreateView):
    model = Author
    fields = ['name']

class AuthorUpdate(UpdateView):
    model = Author
    fields = ['name']

class AuthorDelete(DeleteView):
    model = Author
    success_url = reverse_lazy('author-list')

notes

Here we have to usereverse_lazy()instead ofreverse, because the URL was not loaded when the file was imported.

fieldsProperties work in the same way asModelFormInside ofMetaClassfieldsThe properties are the same. Unless you define the form class in another way, this attribute is required. If not, an error will be raisedImproperlyConfiguredAbnormal.

If you specify bothfieldsandform_classProperty, aImproperlyConfiguredAbnormal.

Changed in Django 1.8:

Omitting the fields attribute was previously allowed, but resulted in the form with all the fields of the model.
Changed in Django 1.8:

Previously, if fields and forms_ If both class are specified, fields will be silently ignored.

Finally, let’s put these new views into urlconf:

#urls.py

from django.conf.urls import url
from myapp.views import AuthorCreate, AuthorUpdate, AuthorDelete

urlpatterns = [
    # ...
    url(r'author/add/$', AuthorCreate.as_view(), name='author_add'),
    url(r'author/(?P<pk>[0-9]+)/$', AuthorUpdate.as_view(), name='author_update'),
    url(r'author/(?P<pk>[0-9]+)/delete/$', AuthorDelete.as_view(), name='author_delete'),
]

notes

These forms inheritSingleObjectTemplateResponseMixin, it usestemplate_name_suffix And construct based on the modeltemplate_name

In this example:

  • CreateViewandUpdateViewusemyapp/author_form.html

  • DeleteViewusemyapp/author_confirm_delete.html

If you want to separateCreateViewandUpdateViewYou can set the template of your view classtemplate_nameortemplate_name_suffix

Model and request.user

To track users who create an object using createview, you can use a custom modelform to do this. First, add a foreign key association to the model:

#models.py

from django.contrib.auth.models import User
from django.db import models

class Author(models.Model):
    name = models.CharField(max_length=200)
    created_by = models.ForeignKey(User)

    # ...

In this view, make sure you don’tcreated_byInclude in the list of fields to edit and overwriteform_valid()To add this user:

#views.py

from django.views.generic.edit import CreateView
from myapp.models import Author

class AuthorCreate(CreateView):
    model = Author
    fields = ['name']

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

Note that you need to uselogin_required()To decorate this view, orform_valid()Process unauthenticated users in.

Ajax example

The following is a simple example of how you can implement a form so that it can work for both Ajax requests and ‘normal’ form post:

from django.http import JsonResponse
from django.views.generic.edit import CreateView
from myapp.models import Author

class AjaxableResponseMixin(object):
    """
    Mixin to add AJAX support to a form.
    Must be used with an object-based FormView (e.g. CreateView)
    """
    def form_invalid(self, form):
        response = super(AjaxableResponseMixin, self).form_invalid(form)
        if self.request.is_ajax():
            return JsonResponse(form.errors, status=400)
        else:
            return response

    def form_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(AjaxableResponseMixin, self).form_valid(form)
        if self.request.is_ajax():
            data = {
                'pk': self.object.pk,
            }
            return JsonResponse(data)
        else:
            return response

class AuthorCreate(AjaxableResponseMixin, CreateView):
    model = Author
    fields = ['name']

translator:Django document collaborative translation team, Original:Built-in editing views

In this paperCC BY-NC-SA 3.0Please keep the author’s signature and the source of the article.

Django document collaborative translation teamThere is a shortage of staff. Interested friends can join us. It is completely public welfare. Communication group: 467338606.