Django - migrating from function based views to class based views

Reading Time : ~ .

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,
                          ['help@micropyramid.com'],
                          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/

    By Posted On
SENIOR DEVELOPER at MICROPYRAMID

Need any Help in your Project?Let's Talk

Latest Comments
Related Articles
How To Write Custom migrations in Django Shirisha Gaddi

This blog post will help you to get deeper into Django Migrations - how Migrations works and how to create or add our custom migrations. ...

Continue Reading...
Custom validations for serializer fields Django Rest Framework Anjaneyulu Batta

we can write custom validations for serializer fields in Django Rest Framework. Validators are used to validate the data whether it is semantically valid or ...

Continue Reading...
django Payu Payment gateway Integration Shirisha Gaddi

In this blog, we will see how to integrate Django and PayU Payment Gateway. To integrate with PayU, we have package called "django-payu" - a ...

Continue Reading...

Subscribe To our news letter

Subscribe to our news letter to receive latest blog posts into your inbox. Please fill your email address in the below form.
*We don't provide your email contact details to any third parties