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 and get_queryset() are the core of the view, determining how to generate the list of records to display on this view.
- paginate_by and get_paginate_by() provide a quick and effortless way to paginate your view
- ordering and get_ordering() determine how the items in the list are sorted. By default, the model’s ordering 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, and pk_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.
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 and template_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 use exclude 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 own Form class to this property to further customize fields & validation.
- success_url and get_sucess_url() can be used to determine where the user lands after the form is successfully processed (by default, the model’s get_absolute_url() is invoked.)
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.
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)
FormView detailed documentation
Conclusion
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!