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