How to Use Class-Based Views in Django (When Not to Use Function-Based Views)

Bilge Demirkaya
Aug 29, 2020 · 3 min read

Saying [that class-based views] is always the superior solution is a mistake.

Nick Coghlan

If you have only used function-based generic views in your Django project so far and find out that they are limited, you should think class-based view as a fresh approach to extending those limitations in more complex projects.

Class-based view

Class-based view is an alternate way of function-based view. In the beginning, there was only function-based view in Django: “Django passed your function an HttpRequest and expected back an HttpResponse.”

Function-based views are obviously useful for simple applications but there is no way to customize or extend them so developers needed an alternative approach.

The reason class-based view is way more flexible and extendible than function-based views is Django uses mixins and toolkit of base classes to build class-based views.

Using class-based views can seem like more complex because same thing can be achieved by function-based method more easily. But on the other hand, without them more advanced designs would be limited.

Implementation of class-based view:

Example of function-based views:

from django.http import HttpResponsedef my_view(request):
if request.method == 'GET':
# <view logic>
return HttpResponse('result')

(taken from docs)

Example of class-based views:

from django.http import HttpResponse
from django.views import View
class MyView(View):
def get(self, request):
# <view logic>
return HttpResponse('result')

(taken from docs)

Now because urls.py expecting from you a function that returns an Http response;above example would have raised an error. But class-based views have an as_view() the method which returns a function that can be called when a request arrives for a URL pattern you have determined for a particular page.

response = MyView.as_view()(request)

after setup() to initialize its attributes anddispatch() to determine whether request method is GET or POST, it returns an HTTP response. But this cycle is more like backstage play. Let’s move on

In order to set this up, in urls.py should be:

urlpatterns = [
path('index', MyView.as_view(),name="index"),
]

instead of:

urlpatterns = [
path('index', views.index,name="index"),
]
  • Since it is returning an Http response like a function-based view, it is possible to use template responses in class view such as to render, redirect, HttpResponseRedirect and so on.

There are two ways to set class attributes;

  1. Python way of subclassing
class StartingView(View):
startwith = "Hello, World!"

def get(self, request):
return HttpResponse(self.startwith)

2. Setting class attributes as a keyword to the as_view() function in urls.py

urlpatterns = [
path('about/', StartingView.as_view(startwith="Hello,World!")),
]
  • Second way is a one-time configuration while in the subclassing method, attributes can be set multiple times.
  • In first way; you can also decorate your view in urls.py like this:
urlpatterns = [
path('index/', login_required(TemplateView.as_view(template_name="secret.html"))),
path('vote/', permission_required('polls.can_vote')(VoteView.as_view())),
]

Conclusion

I have tried to explain the usage of class-based view however I honestly do prefer function-based views for simple cases, especially if I don’t have to repeat the same code. Here is one example:

Let’s say you want to add today’s date for your code. In function-based view you can simply write:

'today': date.today()

With a Class view, on the other hand, what you have to add is this:

def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['today'] = date.today()
return context

As a result, class-based can be hard and complex in most of the situations wherein some situations it is extremely helpful.

First of all, it helps with the DRY code principle ( Don’t Repeat Yourself) Because once you write your class view, you can use it anywhere.

If you do want to integrate your code with Javascript ( or will be using Django Rest Framework) then you will most likely use more class-based views.

Photo by Alex Motoc on Unsplash

The Startup

Get smarter at building your thing. Join The Startup’s +787K followers.

Sign up for Top 10 Stories

By The Startup

Get smarter at building your thing. Subscribe to receive The Startup's top 10 most read stories — delivered straight into your inbox, once a week. Take a look.

By signing up, you will create a Medium account if you don’t already have one. Review our Privacy Policy for more information about our privacy practices.

Check your inbox
Medium sent you an email at to complete your subscription.

Bilge Demirkaya

Written by

Software Engineer at 42 Silicon Valley | Technical Writer at ContentLab.io

The Startup

Get smarter at building your thing. Follow to join The Startup’s +8 million monthly readers & +787K followers.

Bilge Demirkaya

Written by

Software Engineer at 42 Silicon Valley | Technical Writer at ContentLab.io

The Startup

Get smarter at building your thing. Follow to join The Startup’s +8 million monthly readers & +787K followers.

Medium is an open platform where 170 million readers come to find insightful and dynamic thinking. Here, expert and undiscovered voices alike dive into the heart of any topic and bring new ideas to the surface. Learn more

Follow the writers, publications, and topics that matter to you, and you’ll see them on your homepage and in your inbox. Explore

If you have a story to tell, knowledge to share, or a perspective to offer — welcome home. It’s easy and free to post your thinking on any topic. Write on Medium

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store