Django generic base view

Django generic base view

Django supports two types of views

  1. Function based views
  2. Class based views

Function based views are recommended to use when we have less complexity in functionality. But, when we have complex functionality to be implemented then we need to use class based views. Because, class based views are nothing but python classes. It supports OOP's concepts like inheritance and method overloading and method overriding. We can split the complex functionality into classes and methods and combine them using OOP's concepts.

Django provided with generic views for different use cases. The base class for all these generic views is View and all other generic classes inherits it's attributes and methods and extends the required functionalities.

Base View

  • Find the UML diagram for the base view class view

Django View

  • http_method_names attribute used to restrict the http method requests if not required
  • as_view method is the main entry point for a request-response process.
  • http_method_not_allowed method used to raise request method not allowed error.
  • dispatch method is called after as_view is called. It checks the request method GET, POST, etc. and sends routes the request to that specific method if it's implemented otherwise it will call http_method_not_allowed method to raise error method not allowed.

  • Find the request flow in the below diagram

django base view flow

Example implementation of base View

  • Let's see an example use case which will render a contact form for GET request method and sends an email to user when user submits the form.

template.html

<form action="" method="POST">
  {% csrf_token %}
  {{form.as_view()}}
  <input type="submit" />
</form>

forms.py

from django import forms

class ContactForm(forms.Form):
    from_email = forms.EmailField(required=True)
    subject = forms.CharField(required=True)
    message = forms.CharField(widget=forms.Textarea, required=True)

views.py

from django.views.generic import View
from django.core.mail import send_mail
from django.http import HttpResponse
from django.shortcuts import render

from .forms import ContactForm

class ContactView(View):
    def get(self, request):
        template_name = "template.html"
        context = {
            "form": ContactForm()
        }
        return render(request, template_name, context)

    def post(self, request):
        form = ContactForm(request.POST)
        if form.is_valid():
            from_email = form.cleaned_data.get("from_email")
            subject = form.cleaned_data.get("subject")
            message = form.cleaned_data.get("message")
            to_email = "[email protected]"
            send_mail(subject, message, from_email, [to_email])
            return HttpResponse("")
        else:
            template_name = "template.html"
            context = {"form": form}
            return render(request, template_name, context)

urls.py

from . import views

urlpatterns = [
    url('contact/', ContactView.as_view(), name="contact"),
]

If you see the above we have seperated the functionality for get and post requests so that the methods get and post are responsible to handle the request based on request method. If we write same code with function based views we will need to implement multiple if and else conditions and it doesn't allow the easy navigation of the code to change something.

The same can be implemented with FormView with a few lines of code as the view contains above implemented functionality in-built.

Note: It's always recommended to use the class based views if we have complex functionality.