The single most significant advantage in Django class-based views is inheritance. On a large project, it's likely that we will have lots of similar views. Instead of writing the repeated code we can simply have our views inherit from a base view. Also, Django ships with a collection of generic view classes that can be used to do some of the most common tasks.
1. Template View
Function based view
urls.py
from django.conf.urls import url
from . import views
urlpatterns = [
url(r'^about-us/$', views.about_us, name="about_us"),
]
views.py
from django.shortcuts import render
def about_us(request):
return render(request, 'templates/contact.html')
Class based view
urls.py
from django.conf.urls import url
from .views import AboutUs
urlpatterns = [
url(r'^about-us/$', AboutUs.as_view(), name="about_us"),
]
views.py
from django.views.generic import TemplateView
class AboutUs(TemplateView):
template_name = "templates/about.html"
or we can directly write it in "urls.py"
urls.py
from django.conf.urls import url
from django.views.generic import TemplateView
urlpatterns = [
url(r'^about-us/$', TemplateView.as_view(template_name= "templates/about.html"), name="about_us"),
]
2. Detail View
Function based view
urls.py
from django.conf.urls import url
from . import views
urlpatterns = [
url(r'^author/(?P<pk>[0-9]+)/details/$', views.author_details, name="author_details"),
]
views.py
from django.shortcuts import render
from django.shortcuts import get_object_or_404
from books.models import Author
def author_details(request, pk):
author = get_object_or_404(Author, id=pk)
context = {'author': author}
return render(request,
context,
'templates/author_details.html')
Class based view
urls.py
from django.conf.urls import url
from .views import AuthorDetails
urlpatterns = [
url(r'^author/(?P<pk>[0-9]+)/details/$', AuthorDetails.as_view(), name="author_details"),
]
views.py
from django.views.generic import DetailView
from books.models import Author
class AuthorDetails(DetailView):
model = Author
slug_field = 'pk' # for identifying the object uniquely
context_object_name = 'author' # this name is used access the object inside template (it's optional)
template_name = "templates/author_details.html"
we can access object in template as "object" or model name with lowercase letters "modelname" (ex: object.name or author.name)
Note : To send extra context data to the template we can override the super class method get_context_data
from django.views.generic import DetailView
from .models import Author, Book
class AuthorDetails(DetailView):
model = Author
slug_field = 'pk'
template_name = "templates/author_details.html"
def get_context_data(self, **kwargs):
context = super(AuthorDetails, self).get_context_data(**kwargs)
context['book_list'] = Book.objects.filter(author=self.get_object())
return context
3. List View
Function based view
urls.py
from django.conf.urls import url
from . import views
urlpatterns = [
url(r'^authors-list/$', views.authors_list, name="authors_list"),
]
views.py
from django.shortcuts import render
from books.models import Author
def authors_list(request):
authors_list = Author.objects.all()
context = {'authors_list': authors_list}
return render(request,
context,
'templates/authors_list.html')
Class based view
urls.py
from django.conf.urls import url
from .views import AuthorDetails
urlpatterns = [
url(r'^authors-list/$', AuthorsList.as_view(), name="authors_list"),
]
views.py
from django.views.generic import ListView
from books.models import Author
class AuthorsList(ListView):
model = Author
template_name = "templates/authors_list.html"
we can access objects in template as "object_list" or model name with lowercase letters "modelname_list"
List view with dynamic filtering
urls.py
from django.conf.urls import url
from . import views
urlpatterns = [
url(r'^authors-list/subject/(?P<category>[-\w]+)/$', views.authors_list, name="authors_list"),
]
views.py
from django.shortcuts import render
from books.models import Author
def authors_list(request, category):
authors_list = Author.objects.filter(category=category)
context = {'authors_list': authors_list,
'category': category}
return render(request,
context,
'templates/authors_list.html')
Class based view
urls.py
from django.conf.urls import url
from .views import AuthorsList
urlpatterns = [
url(r'^authors-list/subject/(?P<category>)/$', AuthorsList.as_view(), name="authors_list"),
]
views.py
from django.views.generic import ListView
from books.models import Author
class AuthorsList(ListView):
model = Author
template_name = "templates/authors_list.html"
paginate_by = 10 # It will paginate the objects such that each page contains atmost 10 objects
def get_queryset(self):
query_set = self.model.objects.filter(category=self.kwargs.get('category'))
return query_set
we are overriding the super class method "get_queryset" to get desired query set.
4. Form View
forms.py
from django import forms
from django.core.mail import send_mail
class ContactForm(forms.Form):
name = forms.CharField(max_length=100)
subject = forms.CharField(max_length=100, required=False)
email = forms.EmailField()
message = forms.CharField(widget=forms.Textarea)
def send_email(self):
name = self.cleaned_data.get('name', '')
subject = self.cleaned_data.get('subject', '')
email = self.cleaned_data.get('name', '')
message = self.cleaned_data.get('message', '')
send_mail( subject,
message,
email,
['[email protected]'],
fail_silently=False, )
Function based view
urls.py
from django.conf.urls import url
from . import views
urlpatterns = [
url(r'^contact-us/$', views.contact_us, name="contact_us"),
]
views.py
from .forms import ContactForm
django.http import HttpResponseRedirect
def contact_us(request):
form = ContactForm()
if request.POST:
form = ContactForm(request.POST)
if form.is_valid():
form.send_email()
return HttpResponseRedirect("/thanks/")
context = {'form': form}
return render(request,
context,
'templates/contact_us.html')
Class based view
urls.py
from django.conf.urls import url
from .views import ContactUs
urlpatterns = [
url(r'^contact-us/$', ContactUs.as_view(), name="contact_us"),
]
views.py
from django.views.generic.edit import FormView
from .forms import ContactForm
class ContactUs(FormView):
template_name = 'templates/contact_us.html'
form_class = ContactForm
success_url = '/thanks/'
def form_valid(self, form):
form.send_email()
return super(ContactUs, self).form_valid(form)
5. Create View
forms.py
from django import forms
from .models import Author
class AuthorForm(forms.ModelForm):
class Meta:
model = Author
fields = ("first_name",
"last_name",
"about",
"country")
Function based view
urls.py
from django.conf.urls import url
from . import views
urlpatterns = [
url(r'^create-author/$', views.create_author, name="create_author"),
]
views.py
from .forms import AuthorForm
django.http import HttpResponseRedirect
def create_author(request):
form =AuthorForm()
if request.POST:
form = AuthorForm(request.POST)
if form.is_valid():
form.save()
return HttpResponseRedirect("/authors-list/")
context = {'form': form}
return render(request,
context,
'templates/create_author.html')
Class based view
urls.py
from django.conf.urls import url
from .views import CreateAuthor
urlpatterns = [
url(r'^create-author/$', CreateAuthor.as_view(), name="create_author"),
]
views.py
from django.views.generic.edit import CreateView
from .forms import AuthorForm
from .models import Author
class CreateAuthor(CreateView):
model = Author # provide if you don't use model form
template_name = 'templates/create_author.html'
form_class = AuthorForm
success_url = '/authors-list/'
6. Update View
Function based view:
urls.py
from django.conf.urls import url
from . import views
urlpatterns = [
url(r'^update-author/(?P<author_id>[\d]+)/$', views.update_author, name="update_author"),
]
views.py
from django.http import HttpResponseRedirect
from django.shortcuts import get_object_or_404
from .forms import AuthorForm
from .models import Author
def update_author(request, author_id):
author =get_object_or_404(Author, id=author_id)
if request.POST:
form = AuthorForm(request.POST, instance=author)
if form.is_valid():
form.save()
return HttpResponseRedirect("/authors-list/")
form = AuthorForm(instance=author)
context = {'form': form}
return render(request,
context,
'templates/create_author.html')
Class based view
urls.py
from django.conf.urls import url
from .views import UpdateAuthor
urlpatterns = [
url(r'^update-author/(?P<author_id>[\d]+)/$', UpdateAuthor.as_view(), name="update_author"),
]
views.py
from django.views.generic.edit import UpdateView
from .forms import AuthorForm
from .models import Author
class UpdateAuthor(UpdateView):
model = Author # provide if you don't use model form
slug_field = 'author_id'
template_name = 'templates/create_author.html'
form_class = AuthorForm
success_url = '/authors-list/'
7. Delete View
Function based view:
urls.py
from django.conf.urls import url
from . import views
urlpatterns = [
url(r'^delete-author/(?P<author_id>[\d]+)/$', views.delete_author, name="delete_author"),
]
views.py
from django.http import HttpResponseRedirect
from django.shortcuts import get_object_or_404
from .models import Author
def delete_author(request, author_id):
author = get_object_or_404(Author, id=author_id)
author.delete()
return HttpResponseRedirect("/authors-list/")
Class based view
urls.py
from django.conf.urls import url
from .views import DeleteAuthor
urlpatterns = [
url(r'^delete-author/(?P<author_id>[\d]+)/$', DeleteAuthor.as_view(), name="delete_author"),
]
views.py
from django.views.generic.edit import DeleteView
from .models import Author
class DeleteAuthor(DeleteView):
model = Author
slug_field = 'author_id'
success_url = '/authors-list/'
You can always override super class methods if required, see UML diagrams of Django-generic views for better understanding http://epydoc.pythondiary.com/generic-views/