Django: Top 5 Class Based Views
Class Based Views in Django are an incredible tool that reduce boilerplate code and help me get right into the business logic of my apps. This is why for all my Django projects, I rely exclusively on CBVs for all my views.
In this article, I will list out the top 5 CBVs that I use the most often in my Django projects, what they do, and how to make the best use of them.
ListView
By far the most common view I use is ListView
. It operates on multiple records at once, and provides rich functionality out-of-the-box, such as pagination.
Use this view when displaying a list of records for a single model, with or without a filter applied. i.e. Show me a table of all foobar objects with X attribute.
This CBV can be easily extended by overwriting the following attributes and methods:
model
as with other CBVs, determines which model is acted upon.template_name
controls which template to render the view.context_object_name
— Use this to change the name of the variable holding the list of objects being sent to the template. By default, the name of the model is used.queryset
andget_queryset()
are the core of the view, determining how to generate the list of records to display on this view.paginate_by
andget_paginate_by()
provide a quick and effortless way to paginate your view — more on pagination can be found in another article I wrote.ordering
andget_ordering()
determine how the items in the list are sorted. By default, the model’sordering
value is used, but can be overwritten here for this view.- Plus the other usual methods.
Example:
from django.views.generic.list import ListView
from .models import Foobar
class FoobarListView(ListView):
model = Foobar
paginate_by = 25
template_name = 'foobar_list.html'
context_object_name = 'foobars'
queryset = Foobar.objects.filter(my_field='my_value')
More detailed documentation for this CBV can be found on the Django website.
DetailView
The other view I use on an extremely frequent basis is the DetailView
— typically wherever I use the ListView
I also have a matching DetailView
to go with it. Whereas the ListView
operates on multiple records, DetailView
only operates on a single object.
This is extremely useful for showing extensive details on a single record, including any other records from a related model. i.e. Show me everything about foobar object ID 1234.
This CBV can be easily extended by overwriting the attributes and methods noted in the ListView
above, plus:
slug_field
,slug_url_kwarg
, andpk_url_kwarg
control the variable being passed in from URL to this view to uniquely identify the single record that will be displayed on this view.get_object()
defines the queryset which is responsible for fetching the single record for this detail view.- Plus the other usual methods.
Example:
from django.views.generic.detail import DetailView
from .models import Foobar
class FoobarDetailView(DetailView):
template_name = 'foobar_details.html'
model = Foobar
context_object_name = 'foobar'
slug_field = 'foobar_id'
slug_url_kwarg = 'foobar_id'
More detailed documentation for this CBV can be found on the Django website.
CreateView
Another CBV which comes up often for me is the CreateView
. In short, CreateView
is used for managing the form used by users to insert new records of a model. This view is extremely useful because of the sheer amount of work it does automatically: it not only automatically generates the form the user fills out with all the relevant fields, but it also handles the form validation and processing as well!
This CBV can be easily extended by overwriting the following attributes and methods:
model
andtemplate_name
— like the previous CBVs.fields
takes in a list of field names to automatically include on the form. Any field not listed here will not be included. Another approach is to useexclude
which would mean every field from the model is used except the ones in this list.form_class
exists as another alternative to the above: you can provide your ownForm
class to this property to further customize fields & validation.success_url
andget_sucess_url()
can be used to determine where the user lands after the form is successfully processed (by default, the model’sget_absolute_url()
is invoked.)- Plus the other usual methods.
Example:
from django.views.generic.edit import CreateView
from .models import Foobar
class FoobarCreateView(CreateView):
model = Foobar
fields = ["first_field", "second_field", "third_field"]
success_url = "/home"
CreateView detailed documentation.
UpdateView
Whereas CreateView
is used for creating new records for a model, UpdateView
edits existing records for a model, as the name implies. Like CreateView
above, this view completely handles all the form-related activities for us so we don’t have to worry about any of it.
UpdateView
has all the same attributes and methods to overwrite as CreateView
above, plus the ones from the DetailView
above, specifically slug_field
, slug_url_kwarg
.
from django.views.generic.edit import UpdateView
from .models import Foobar
class FoobarUpdateView(UpdateView):
template_name = 'foobar_update.html'
model = Foobar
slug_field = 'foobar_id'
slug_url_kwarg = 'foobar_id'
context_object_name = 'foobar'
fields = ["first_field", "second_field", "third_field"]
UpdateView detailed documentation.
FormView
Finally is the more generic FormView
— an ancestor of the two classes above. I generally use this view to perform generic non-create and non-update related actions on record(s) for a single model which require user input.
For example, one FormView
I have is responsible for E-mailling a “report” of recent records to the E-mail address the user supplied. Another FormView
takes user input, and using the information provided by the user, sends off an HTTP request to the REST API for another service.
Example:
from django.views.generic.edit import FormView
from django import forms
from .models import Foobar
from .my_utils import send_email
class FooBarEmailForm(forms.Form):
recipients = forms.CharField(required=True)
subject = forms.CharField(required=True)
message = forms.CharField(required=True, widget=forms.Textarea)
class FoobarEmailView(FormView):
template_name = 'foobar_email.html'
model = Foobar
context_object_name = 'foobar'
form_class = FooBarEmailForm
def form_valid(self, form):
recipients = form.cleaned_data.get('recipients')
message = form.cleaned_data.get('message')
subject = form.cleaned_data.get('subject')
send_email(subject, recipients, message)
return super().form_valid(form)
While there are way more CBVs available, these the top 5 I use the most often, and the most critical to master. A complete list of all CBVs available can be found on the Django website.
Are there any CBVs you use on a regular basis not listed here? Sound off in the comments!