django class based generic views¶
In web application development, it's possible to have a repeated patterns again and again. so, Django comes with solution. The solution is generic class based views.
Advantanges of generic class based views¶
- Django’s generic views were developed to ease that pain.
- Generic views abstracted the common functionality so, we can write less code and get the functionality done quickly.
- We can inherit the generic views and extend the functionality so that we can speed up the development.
- Code will be clean and well organized
Disadvantages of generic class based views¶
- It looks some what difficult when compare to function based views because of the abstraction of the functionality provided by the class based views.
- It will be difficult to understand the code when you didn't know OOP's concepts atleast the inheritance concept.
Generic views¶
We have the following views provided by django
- View
- TemplateView
- FormView
- CreateView
- DetailView
- ListView
- UpdateView
- DeleteView
Note: Django also provides other class based views but these are used frequently.
Base class - View¶
- It's the base class for all generic views.
- We need to implement the HTTP request methods
as_view
is the class method which returns the view.
Let's see an example view to return simple HTTP response
views.py
from django.views.generic import View
from django.http import HttpResponse
class SimpleView(View):
def get(self, request):
return HttpResponse("Hello")
urls.py
from django.urls import path
from .views import SimpleView
urlpatterns = [
path("simple-view/", SimpleView.as_view(), name="simple")
]
Generic TemplateView¶
- It's used to render the template with context
- It inherits the base class
View
- We just need to provide the template path to render the template with attribute
teamplate_name
. - We can pass the context to template by method
get_context_data
Let's see an example to terms page
terms.html
<html> <body> <h1>Hello, {{user}}</h1> </body> </html>
views.py
from django.views.generic import TemplateView
class TermsView(TemplateView):
template_name = "terms.html"
def get_context_data(self, *args, **kwargs):
context = {
"user": "Anji"
}
return context
urls.py
from django.urls import path
from .views import TermsView
urlpatterns = [
path("terms/", TermsView.as_view(), name="terms")
]
Generic FormView
¶
- It's used to collect the input from the user.
- we need to inherit the
FormView
to the current view to implement it. - It takes attributes
form_class
,template_name
andsuccess_url
form_valid
method is to write our business logic. It's called when form is valid.
Let's see an example
forms.py
from django import forms
class CityForm(forms.Form):
name = forms.CharField()
description = forms.CharField(widget=forms.Textarea)
city_form.html
<form method="post">
{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="Save">
</form>
views.py
from django.views.generic.edit import FormView
from .forms import CityForm
class CityFormView(FormView):
form_class = CityForm
template_name = "city_form.html"
success_url ="/thanks/"
def form_valid(self, form):
# our business logic here
return super().form_valid(form)
urls.py
from django.urls import path
from .views import CityFormView
urlpatterns = [
path("terms/", CityFormView.as_view(), name="city_form")
]
Generic CreateView
¶
- It's used to create an instance of a table in the database.
- Organization of code related to specific HTTP methods (GET, POST, etc.) can be addressed by separate methods instead of conditional branching.
usecase: Let's write a code to add the city details to the city table.
models.py
from django.db import models
class City(models.Model):
title = models.CharField(max_length = 200)
description = models.TextField()
def __str__(self):
return self.title
city_form.html
<form method="POST" enctype="multipart/form-data"> <!-- Security token --> {% csrf_token %} <!-- Using the formset --> {{ form.as_p }} <input type="submit" value="Submit"> </form>
views.py
from django.views.generic.edit import CreateView
from .models import City
class CityCreateView(CreateView):
model = City
fields = ['title', 'description']
template_name = "city_form.html"
urls.py
from django.urls import path
from .views import CityView
urlpatterns = [
path('city', CityCreateView.as_view(), name="city-create"),
]
Like, above we can write create functionality with very minimal code. This is how django class based views comes in to handy.
Generic DetailView
¶
- It's used to retrive the instance from the database and show the info to the user.
- It requires minimal effort to implement it with generic CBV(i.e class based views) views.
- Let's use the same model
City
fromCreateView
example. - It sends model instance as
object
to template context - It uses
pk
url kwarg to find the correct model instance in the database table.
Let's see an example implementation
city_detail.html
<h1>{{ object.title }}</h1>
<p>{{ object.description }}</p>
views.py
from django.views.generic.detail import DetailView
from .models import City
class CityDetailView(DetailView):
model = City
template_name = "city_detail.html"
urls.py
from django.urls import path
from .views import CityDetailView
urlpatterns = [
path('city/<pk>/', CityDetailView.as_view(), name="city-detail"),
]
It's that simple to implement the django generic detail view.
Generic ListView¶
- It's used to list/show all objects/rows in the database table to user.
- It comes with pagination as it's difficult to handle large data.
- It sends all objects or paginated objects to template context with name
object_list
Let's see an example
city_list.html
<ul>
<!-- Iterate over object_list -->
{% for object in object_list %}
<!-- Display Objects -->
<li>{{ object.title }}</li>
<li>{{ object.description }}</li>
<hr/>
<!-- If objet_list is empty -->
{% empty %}
<li>No objects yet.</li>
{% endfor %}
</ul>
views.py
from django.views.generic.list import ListView
from .models import City
class CityListView(ListView):
model = City
urls.py
from django.urls import path
from .views import CityListView
urlpatterns = [
path('all-cities/', CityListView.as_view(), name="city-list"),
]
It's that simple to implement the generic class based listview in django.
Generic UpdateView¶
- It's used to update the existing object/row in the database table.
- It automatically generates the form from the model and sends to the template context
- It can be accessed with name
form
in the template - It identifies the object with url kwarg
pk
Let's see an example
city_update.html
<form method="post">
{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="Save">
</form>
views.py
from django.views.generic.edit import UpdateView
from .models import City
class CityUpdateView(UpdateView):
model = City
fields = ["title","description"]
success_url ="/"
urls.py
from django.urls import path
from .views import CityUpdateView
urlpatterns = [
path('city/<pk>/update', CityUpdateView.as_view(), name="city-update"),
]
That's how we implement the update view with class based UpdateView in django.
Generic DeleteView¶
- It's used to remove/delete an instance from the database table.
- DeleteView identifies the correct instance with the url kwarg
pk
Let's see an example
city_delete.html
<form method="post">
{% csrf_token %}
<p>Are you sure you want to delete "{{ object }}"?</p>
<input type="submit" value="Confirm">
</form>
views.py
from django.views.generic.edit import DeleteView
from .models import City
class CityDeleteView(DeleteView):
model = City
success_url ="/"
urls.py
from django.urls import path
from .views import CityDeleteView
urlpatterns = [
path('city/<pk>/delete/', CityDeleteView.as_view(), name="city-delete"),
]
We have seen simple examples to use class based views in django. Create a djano app and try it out.
Reference: https://docs.djangoproject.com/en/3.2/topics/class-based-views/generic-display/