Skip to content

Class-Based Views

View class

Views can be not only functions but also classes. We call such views class-based-view. They must inherit from the View class in the django.views module.

from django.shortcuts import render
from django.views import View

from viewer.models import Movie


class MoviesView(View):
  def get(self, request):
    return render(
      request, template_name='movies.html',
      context={'movies': Movie.objects.all()}
    )

The View class has methods with names corresponding to HTTP methods (get -> GET, post -> POST, put -> PUT, etc.). Their arguments (apart from self), as in the case of function views, are the query object, commonly called request, and the arguments named from the regular expression from the URL. These methods are run by the dispatch method, which checks the method used to execute the HTTP request. Usually we don't reload the method dispatch, but methods get, post, put, etc. With this pattern, we're allowing Django to automate this one decision node.

To register a view in the urls.py file, we need to call the as_view view class function. This function returns a view function based on the implemented class.

from django.contrib import admin
from django.urls import path

from viewer.models import Genre, Movie
from viewer.views import MoviesView

admin.site.register(Genre)
admin.site.register(Movie)

urlpatterns = [
  path('admin/', admin.site.urls),
  path('', MoviesView.as_view(), name='index')
]

TemplateView class

When using a template, we can inherit from the TemplateView class. Then we only set the name of the template that we want to use to render the page in the static field template_name. To enter contextual data, set the dictionary in the extra_context field.

from django.views.generic import TemplateView

from viewer.models import Movie


class MoviesView(TemplateView):
  template_name = 'movies.html'
  extra_context = {'movies': Movie.objects.all()}

ListView class

To generate views fed with data from models we can use generic views. The first is ListView.

from django.views.generic import ListView

from viewer.models import Movie


class MoviesView(ListView):
  template_name = 'movies.html'
  model = Movie
{% extends "base.html" %}

{% block content %}
  <h1>Welcome to HollyMovies!</h1>
  <ul>
    {% for movie in object_list %}
      <li>
        {{ movie.title }} ({{ movie.released.year }}) - {{ movie.genre.name }}
      </li>
    {% endfor %}
  </ul>
{% endblock %}

ListView places the objects from the database in a context variable named object_list, so we don't even have to provide the context, because the objects are automatically placed in it based on the indicated model.

CBV > function view

CBV surpasses function views in many aspects:

  • Time saving

  • Code saving

  • Django implements the logic for us

  • We only declare what effect we want to achieve

  • The code is cleaner because it doesn't have long functions

  • We have an architecture proposal so we don't have to invent our own