Django CRUD Operation using Class-Based Views

Django CRUD Operation using Class-Based Views

Hello Techies,

Django has two types of views. Class-Based Views, and Function-Based Views. So in this blog, I’m going to discuss Django CRUD Operation using Class-Based Views with examples. CRUD operations are common tasks in many web applications. So let’s take a  step-by-step look at how to perform this Django CRUD operation using class-based views.

Refer the below Articles to check how to create Django Projects & CRUD operation using Function Based View:

1) How to create Django project
2) Django CRUD Operation using Function-Based Views

1. Introduction

Django is a Python-based web framework that follows the MVT (Model View Template) pattern and allows you to quickly create web applications. It offers built-in class-based generic views for CRUD operations so that you can easily perform CRUD operations using these views.

Django CRUD Operation using Class-Based Views. The sample project view you are working on in this tutorial.

Generic Class Based View

Django generic views have been developed as shortcuts for common usage methods such as displaying object details.

They take some of the common methods found in view development and abstract them so that you can quickly write common views of data without writing too much code.

5 different Django class-based generic views

  • ListView: This class helps you to view the list of objects.
  • CreateView: This class helps you to create new objects. 
  • DetailView: This class helps you to view the details of a particular object.
  • UpdateView: This class helps you to update a particular object.
  • DeleteView: This class helps you to delete a particular object.

2. Requirements

  • Python installed in the machine: Django is based on Python so you need to have Python installed in your machine.
  • Virtual Environment: Install virtual environment after Python installation. Virtual environment installation will vary according to your OS.
  • Django Installation:  Once the above requirements are met, install Django, and start to implement the Django CRUD operation using the Class-Based Views project.

For Python, Virtual Environment & Django installation check our previous blogs. Below are the links:

For Windows: https://techpluslifestyle.com/technology/how-to-install-django-3-on-windows

For Ubuntu: https://techpluslifestyle.com/technology/how-to-install-django-3-on-ubuntu

Let’s create an application that is based on CMS. So in this application, we are using Django CRUD operation using class-based views (add, delete, create, display, and list blog views). There are two options for viewing and managing blogs. I’m using the SQLite database. If you want to use another database, you can configure it in the settings.py file, and then you can use the new database.


3. Django CRUD Operation using Class-Based Views

Let’s start with the Django class-based views tutorial.

Base.html

To avoid duplication in the other templates use the below base.html code.

# templates/base.html

<!DOCTYPE html>
<html lang="en">

<head>

  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
  <meta name="description" content="">
  <meta name="author" content="">

  <title>TechPlusLifestyle - Django Crud Operation Class Based-View</title>

  <!-- Bootstrap core CSS -->
  <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css" integrity="sha384-JcKb8q3iqJ61gNV9KGb8thSsNjpSL0n8PARn9HuZOnIxN0hoP+VmmDGMN5t9UJ0Z" crossorigin="anonymous">
</head>

<body>

  <!-- Navigation -->
  <nav class="navbar navbar-expand-lg navbar-dark bg-dark static-top">
    <div class="container">
      <a class="navbar-brand" href="#">LOGO</a>
      <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarResponsive" aria-controls="navbarResponsive" aria-expanded="false" aria-label="Toggle navigation">
        <span class="navbar-toggler-icon"></span>
      </button>
      <div class="collapse navbar-collapse" id="navbarResponsive">
        <ul class="navbar-nav ml-auto">
          <li class="nav-item">
            <a class="nav-link" href="{% url 'home' %}">Home
              <span class="sr-only">(current)</span>
            </a>
          </li>
          <li class="nav-item">
            <a class="nav-link" href="{% url 'manage_post_list' %}">Manage Post</a>
          </li>
        </ul>
      </div>
    </div>
  </nav>

  <!-- Page Content -->
  <div class="container">
    <div class="row">
      <div class="col-lg-12">
        {% block content %}
        {% endblock %}
      </div>
    </div>
  </div>

  <!-- Bootstrap core JavaScript -->
  <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.slim.min.js"></script>
  <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.bundle.min.js" integrity="sha384-LtrjvnR4Twt/qOuYxE721u19sVFLVSA4hf/rRt6PrZTmiPltdZcI7q7PXQBYTKyf" crossorigin="anonymous"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/tether/1.4.0/js/tether.min.js" integrity="sha384-DztdAPBWPRXSA/3eYEEUWrWCy7G5KFbe8fFjk5JAIxUYHKkDx6Qin1DkWx51bBrb" crossorigin="anonymous"></script></body>
  <script src="https://getbootstrap.com/docs/4.0/assets/js/vendor/holder.min.js"></script>
</html>

Change the below code in settings.py file.

# settings.py

[os.path.join(BASE_DIR, 'templates')]

Create a separate blog app in this project and add model.py, view.py, url.py, and form.py files to this app. In short, we will put all the source code related to the blog in this app. Once this app is created, add it to the INSTALLED_APPS list in the settings.py file as well as include in the urls.py file.

# settings.py

INSTALLED_APPS = [
       'django.contrib.admin',
       'django.contrib.auth',
       'django.contrib.contenttypes',
       'django.contrib.sessions',
       'django.contrib.messages',
       'django.contrib.staticfiles',
       'blog'
]
# django_crud_class_based_view/urls.py

from django.contrib import admin
from django.urls import path, include

urlpatterns = [
path('admin/', admin.site.urls),
path('', include("blog.urls")),
]

Let’s create a blog model in the app to store multiple fields related to the blog, such as slugs, excerpt, content, author name, blog status, and publish date.

Below is the code for the blog model.

# blog/models.py

from django.db import models
from django.utils import timezone


class Blogs(models.Model):
    class Meta:
        db_table = 'blogs'

    id = models.AutoField(primary_key=True)
    title = models.CharField(max_length=150)
    slug = models.SlugField(max_length=100, unique=True)
    content = models.TextField()
    excerpt = models.TextField()
    published_at = models.DateTimeField(default=timezone.now)
    status = models.CharField(max_length=10, default='draft')
    author = models.CharField(max_length=500)


3.1 ListView

  • The ListView represent/Display a list of objects.
  • It is intended to be used to output multiple objects.
  • ListView can be paginated.

Check out more details about ListView on the official site there.

To create the post list view we will use the Django ListView.

Add the below code in the blog/urls.py file.

# blog/urls.py

from django.urls import path
from .views import *

urlpatterns = [
    path('', IndexView.as_view(), name="home"),
]

The below code is to list the all posts which we had created. I have used the queryset to sort the post by the published date.

# blog/views.py

from django.views.generic import ListView
from .models import Blogs


class IndexView(ListView):
    model = Blogs
    queryset = Blogs.objects.filter(status='published').all(). \
        order_by('-published_at')
    template_name = 'blog/list_view.html'
    context_object_name = 'index_post_list'

Now we will add the template for post list view. Below is the HTML code for list view.

# templates/blog/list_view.html

{% extends 'base.html' %}

{% block content %}
  <div class="album py-5">
    <div class="container">
      <!-- Three columns of text below the carousel -->
      <div class="row">
        {% if object_list %}
          {% for each in index_post_list %}
            <div class="col-lg-4">
              <img class="rounded-circle" src="data:image/gif;base64,R0lGODlhAQABAIAAAHd3dwAAACH5BAAAAAAALAAAAAABAAEAAAICRAEAOw==" alt="Generic placeholder image" width="140" height="140">
              <h2>{{each.title}}</h2>
              <p>{{each.excerpt}}</p>
              <p><a class="btn btn-secondary" href="{% url 'post_detail_view'  slug=each.slug %}" role="button">View details &raquo;</a></p>
            </div><!-- /.col-lg-4 -->
          {% endfor %}
        {% else %}
            No Post Found
        {% endif %}
      </div>
    </div><!-- /.row -->
  </div>
{% endblock %}

Rendered HTML

Django CRUD Operation using Class-Based Views (ListView)

With this our class based list view was completed now will check the detail view.


3.2 Detail View

  • Present detail of a single model instance.
  • Intended to be used with one object only.
  • Must be called – object pk or a slug in the URLconf.

Check out more details about DetailView on the official site there.

To check the post details view we will use the Django DetailView.

Add the below code in the blog/urls.py file.

# blog/urls.py

from django.urls import path
from .views import *

urlpatterns = [
    path('<slug:slug>', DetailedView.as_view(), name="post_detail_view"),
   ]

Add the below code in the blog/views.py.

# blog/views.py

from django.views.generic import DetailView
from .models import Blogs


class DetailedView(DetailView):
    model = Blogs
    template_name = 'blog/detail_view.html'
    context_object_name = 'post'

Now we will add the template for the Post Detail view. Add the below code in templates/blog/detail_view.html.

# templates/blog/detail_view.html

{% extends 'base.html' %}
{% block title %}
{{post.title}}
{% endblock %}
{% block content %}
    <div class="container">
        <div class="row justify-content-md-center pt-5">
        <div class="col-md-8">
          <div class="col-12"><h1>{{post.title}}</h1></div>
            <br/>
            <br/>
            <div class="col-12"><p><b>{{post.published_at | date:"M d, Y"}} by {{post.author}}</b></p></div>
            <br/>
          <div class="col-12"><p>{{post.content|safe}}</p></div>
        </div>
        </div>
      </div>
{% endblock %}

Rendered HTML

Django CRUD Operation using Class-Based Views (DetailView)

With this we completed our second class-based view. Now let’s move on to the third which is Create View.

Before creating the create a view, we will add the Managed Posts section, where we will include the view (such as editing views and deleting the list).

Manage Post

This page will be a landing page. We will show all posts list (such as draft and published status) to the editors who have an access to create, edit and delete posts.

Add the below code in blog/urls.py.

from django.urls import path
from .views import *

urlpatterns = [
    path('blog/manage_post_list', ManagePostList.as_view(), name="manage_post_list"),
]

Below code for the views.

# blog/views.py

from django.views.generic import ListView
from .models import Blogs


class ManagePostList(ListView):
    model = Blogs
    template_name = 'blog/manage_post_list.html'
    context_object_name = 'manage_post_list'


Template to manage the post.

# templates/blog/manage_post_list.html

{% extends 'base.html' %}

{% block content %}
  <br/>
  <div>
        <a class="btn btn-secondary" href="{% url 'add_post' %}" role="button">Add Post</a>
  </div>
  <div class="album py-5 bg-light">
    <div class="container">
      <!-- Three columns of text below the carousel -->
      <div class="row">
        {% if object_list %}
          {% for each in manage_post_list %}
            <div class="card mb-4 box-shadow">
              <img class="card-img-top" data-src="holder.js/100px225?theme=thumb&bg=55595c&fg=eceeef&text=Thumbnail" alt="Card image cap">
              <div class="card-body">
                  <p class="card-text">{{each.title}}</p>
                  <div class="d-flex justify-content-between align-items-center">
                    <div class="btn-group">
                      <a class="btn btn-sm btn-outline-secondary" href="{% url 'edit_post' each.id %}" role="button">Edit</a>
                      <a class="btn btn-sm btn-outline-secondary" href="{% url 'delete_post' each.id %}" role="button">Delete</a>
                    </div>
                  </div>
              </div>
            </div><!-- /.col-lg-4 -->
          {% endfor %}
        {% else %}
            No Post Found
        {% endif %}
      </div>
    </div><!-- /.row -->
  </div>
{% endblock %}

Rendered HTML

Django CRUD Operation using Class-Based Views (List View For Manage Post)

3.3 CreateView

  • A view – displays a form for creating an object.
  • Purpose of this view is to creating an object, redisplaying the form with validation errors (if any) and saving the object.

Check out more details about CreateView on the official site there.

Now we will use the CreateView class to create a post.

Below code to add URL for creating posts.

# blog/urls.py

from django.urls import path
from .views import *

urlpatterns = [

    path('blog/add_post', AddView.as_view(), name="add_post"),
]

Add below code in blog/views.py

# blog/views.py

from django.views.generic import CreateView

from .models import Blogs
from .forms import BlogForm


class AddView(CreateView):
    model = Blogs
    form_class = BlogForm
    template_name = 'blog/add_view.html'
    success_url = '/'

Now we need form validation as well as we need to give some CSS classes in the template field to decorate the template for which we need the form.py file. Below is the code we are going to use in the form.py file.

# blog/forms.py

from django import forms
from .models import Blogs


class BlogForm(forms.ModelForm):
    options = (
        ('draft', 'Draft'),
        ('published', 'Published'),
    )
    title = forms.CharField(widget=forms.TextInput(attrs={'class': 'form-control'}))
    slug = forms.SlugField(widget=forms.TextInput(attrs={'class': 'form-control'}))
    content = forms.CharField(widget=forms.Textarea(attrs={'class': 'form-control'}))
    excerpt = forms.CharField(widget=forms.Textarea(attrs={'class': 'form-control'}))
    status = forms.CharField(widget=forms.Select(choices=options, attrs={'class': 'form-control'}))
    author = forms.CharField(widget=forms.TextInput(attrs={'class': 'form-control'}))

    class Meta:
        model = Blogs
        fields = ['title', 'slug', 'excerpt', 'content', 'status', 'author']

Template for the Post create view. Add the below code to templates/blog/add_view.html.

# templates/blog/add_view.html

{% extends 'base.html' %}

{% block content %}

<div class="container pt-5">
    <form method="post" novalidate>
        {% csrf_token %}
        {% for field in form.visible_fields %}
            <div class="form-group">
                <label for="{{ field.id_for_label }}">{{field.label}}</label>
                {{field}}
                {% for error in field.errors %}
                    <span class="help-block" style="color:red">{{error}}</span>
                {% endfor %}
            </div>
        {% endfor %}
        <div>
            <button type="submit" class="btn btn-success">Submit</button>
            <a href="{% url 'home' %}" class="btn btn-default">Cancel</a>
        </div>
    </form>
</div>

{% endblock %}

Rendered HTML

Django CRUD Operation using Class-Based Views (CreateView)

Rendered HTML With Validation

Django CRUD Operation using Class-Based Views (CreateView Validation)

With this, we are done with our create view.


3.4 UpdateView

  • Retrieve specific object/data.
  • Purpose of this view is to editing an existing object, redisplaying the form with validation errors (if any) and saving changes to the object.

Check out more details about UpdateView on the official site there.

Now we will create an update view for the post so that if the authors want to improve any post they can do it easily.

Below code for URL.

# blog/urls.py

from django.urls import path
from .views import *

urlpatterns = [
path('blog/edit_post/<int:pk>', EditView.as_view(), name="edit_post"),
]

Add the below code in views.py file.

# blog/views.py

from django.views.generic import UpdateView

from .models import Blogs
from .forms import BlogForm

class EditView(UpdateView):
    model = Blogs
    form_class = BlogForm
    pk_url_kwarg = 'pk'
    template_name = 'blog/edit_view.html'
    success_url = '/blog/manage_post_list'

In the above code I have used pk_url_kwarg which will return the post id, using this we can update specific post.

Template for the Update post.

# templates/blog/edit_view.html

{% extends 'base.html' %}

{% block content %}

<div class="container pt-5">
    <form method="post" novalidate>
        {% csrf_token %}
        {% for field in form.visible_fields %}
            <div class="form-group">
                <label for="{{ field.id_for_label }}">{{field.label}}</label>
                {{field}}
                {% for error in field.errors %}
                    <span class="help-block" style="color:red">{{error}}</span>
                {% endfor %}
            </div>
        {% endfor %}
        <div>
            <button type="submit" class="btn btn-success">Submit</button>
            <a href="{% url 'home' %}" class="btn btn-default">Cancel</a>
        </div>
    </form>
</div>

{% endblock %}

Rendered HTML

Django CRUD Operation using Class-Based Views (UpdateView)

This completes your update view. Let’s move on to the last Django class-based view which is Delete View.


3.5 DeleteView

  • This view displays a confirmation page and deletes an existing object.
  • If this view is fetched via GET, it will display the confirmation page which should contain the form posted at the same URL. Only the specified object will be deleted if the request method is POST.

Check out more details about DeleteView on the official site there.

Now we will create the DeleteView.

Add the following code in urls.py file.

# blog/urls.py

from django.urls import path
from .views import *

urlpatterns = [
path('blog/edit_post/<int:pk>', EditView.as_view(), name="edit_post"),
]

Add the below code in views.py file.

# blog/views.py

from django.views.generic import DeleteView
from .models import Blogs

class DeletePostView(DeleteView):
    model = Blogs
    pk_url_kwarg = 'pk'
    template_name = 'blog/delete_view.html'
    success_url = '/blog/manage_post_list'

Template code for the Delete view.

# templates/blog/delete_view.html

{% extends 'base.html' %}

{% block content %}

<div class="container pt-5">
    <form method="post" novalidate>
        {% csrf_token %}
        <p>Are you sure you want to delete post "{{ object.title }}"?</p>
        <input type="submit" value="confirm">
    </form>
</div>

{% endblock %}

Rendered HTML

Django CRUD Operation using Class-Based Views (DeleteView)

FAQ on Django CRUD Operation using Class-Based Views

  1. What is CRUD operations Django?

    Django is a Python-based web framework that follows the MVT (Model View Template) pattern and allows you to quickly create web applications. It offers built-in class-based generic views for CRUD operations. CRUD in general means Creating, Retrieving, Updating and Deleting operations on a table in a database.

  2. What is class based view in Django?

    Class-based view is an alternative to function-based view. They do not replace function-based views, but have some distinct differences and advantages over function-based views.

  3. What is generic views in Django?

    Django generic views have been developed as shortcuts for common usage methods such as displaying object details.
    They take some of the common methods found in view development and abstract them so that you can quickly write common views of data without writing too much code.

  4. What is DetailView in Django?

    Django DetailView should be used when you want to present detail of a single model instance. Its purpose is to use with only one object.


Here we are done with all the steps of Django CRUD Operation using Class-Based Views.

I hope you understand all the steps which I have covered in this blog which is based on Django CRUD Operation using Class-Based Views. If still you have any query do comment below.

Refer the GIT source code for Django CRUD Operation using Class-Based Views project.

Leave a Comment