Django search and pagination Features using Mysql Database

Django search and pagination

Hello Techies,

This blog is on the Django search and pagination Feature. Step-by-step we will check how to develop Django search and pagination features by using Mysql Database. So stay connected to this blog because this blog is not only about Django search and pagination but you can also learn how to develop CRUD operation with these features. This application will help you with the Python interview round as most of the companies asks you to develop a Django CRUD application with search and pagination features.

Let’s start developing this application step by step.

I hope you are reading this blog which means you know how to set up Django application. If you don’t know how to set up Django then check our previous blogs For Python, Virtual Environment & Django installation.

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

Requirements:

  1. Python Installation
  2. Virtual Environment Installation
  3. Django Installation
  4. Mysql Installation

Let’s create an application that is based on the Employee Application. So in this application, we are using Django CRUD operation with Django search and pagination Features. I’m using the MySql 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 for your application.

Steps: Django search and pagination

As I said we are using Mysql Database so for this we need to configure the database in settings.py file check the below code.

# settings.py

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
 #engine name
        'NAME': 'django_crud_with_search_and_pagination',
 #db name
        'USER': 'root',
 #db username
        'PASSWORD': 'root', 
#db password
        'HOST': 'localhost',
 # db hostname
        'PORT': '3306',
 # db port
    }
}

Change the below code in settings.py file.

# settings.py

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

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

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>Employee Details</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>
        </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://stackpath.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.bundle.min.js"></script>
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
</body>
</html>

Create a separate app in this project and add models.py, views.py, urls.py and forms.py files to this app. In short, we will put all the source code related to the Employee application in this app. Once this app is created, add it to the INSTALLED_APPS list in the settings.py file as well as 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',
   'app'
]
# django_crud_with_search_and_pagination/urls.py

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

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

Below is the Project file structure.

Let’s create a model in the app to store multiple fields related to the employee application, such as firstName, lastName, email, age, is_active, created_at, and updated_at.

Below is the code for the Employee model.

# app/models.py

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


class Employee(models.Model):
    class Meta:
        db_table = 'employee'

    id = models.AutoField(primary_key=True)
    firstName = models.CharField(max_length=255)
    lastName = models.CharField(max_length=255)
    email = models.EmailField()
    age = models.IntegerField()
    is_active = models.BooleanField(default=True)
    created_at = models.DateTimeField(default=timezone.now)
    updated_at = models.DateTimeField(default=timezone.now)

Landing Page

Add the below code in the app/urls.py file for the index page.

# app/urls.py

from django.urls import path

from .views import *

urlpatterns = [

    path('', UsersIndex.as_view(), name='home'),
]

Views for the landing page.

# app/views.py

from django.views import View
from django.shortcuts import render, redirect
from django.http import JsonResponse
from django.views.generic import TemplateView, ListView
from django.contrib import messages
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
from django.db.models import Q

from .forms import EmployeeForm
from .models import Employee


class UsersIndex(TemplateView):
    template_name = 'app/index.html'

    def get(self, request, *args, **kwargs):
        """
        Return the list of all the active user's data.
        """
        return render(request, self.template_name)

HTML Template for the index page.

# templates/app/index.html

{% extends 'base.html' %}
{% load static%}

{% block content %}
<!-- Body Elements -->
<div class="content-wrapper">
    <div class="container">
        <form method="get" class = "marketsearch">
            <h1>
                 Employee List
            </h1>
            <br/>
            <br/>

            <div class="displayData-container container">
                <div class="alert alert-success" id="delete_success" style="display:none !important">
                    <button class="close" data-dismiss="alert" type="button">X</button>
                    <strong>Success!</strong> Employee Deleted Successfully
                </div>

                {% if messages %}
                    {% for message in messages %}
                        <div class="alert alert-{{ message.tags }}">
                            <button class="close" data-dismiss="alert" type="button">X</button>
                            <strong>Success!</strong> {{ message }}
                        </div>
                    {% endfor %}
                {% endif %}

                <div class="clearfix">
                    <div class="pull-left">
                        <input name="filter" type="text" value=""  placeholder="Search By First Name" autocomplete="off" class="form-control-sm fa fa-search search form-control"/>
                        <input name="sortfn" id="sortbyfn"  type="hidden" value="-firstName"/>
                        <input name="sortln" id="sortbyln"  type="hidden" value="-lastName"/>
                        <input name="sortemail" id="sortbyemail"  type="hidden" value="-email"/>
                        <input name="sortage" id="sortbyage"  type="hidden" value="-age"/>
                        <input name="click" id="click"  type="hidden" value="0"/>
                    </div>
                    <div class="pull-right">
                       <a class="btn btn-secondary" href="{% url 'add_emp' %}" role="button">Add Employee</a>
                    </div>
                </div>
                <br/>
                <div id="results">

                </div>
            </div>
            <input id="autoid" name="autoid" type="hidden" value="">
        </form>

        <div class="modal" id="myModal">
    <div class="modal-dialog">
        <div class="modal-content">

            <!-- Modal Header -->
            <div class="modal-header">
                <h4 class="modal-title">Are you sure you want to Delete : <span id="deleting_field"></span> this employee</h4>
                <button class="close" data-dismiss="modal" type="button">&times;</button>
            </div>

            <!-- Modal body -->
            <div class="modal-body">
                <form id="updateStatusFrm">
                    <button class="btn btn-primary" onclick="javascript: deleteemp('');" type="button"><i class="fa fa-check ico-mar"></i>Yes
                    </button>

                    <button class="btn btn-danger" data-dismiss="modal" type="button">
                        <i class="fa fa-times ico-mar"></i>No
                    </button>
                </form>
            </div>
        </div>
    </div>
</div>
    </div>
</div>
<script src="https://code.jquery.com/jquery-3.4.1.min.js"></script>
<script type="text/javascript" src="{% static 'js/emp.js' %}"></script>
<link href="http://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css" rel="stylesheet">

{% endblock %}

Django search and pagination with ListView

Add the below code for Django search and pagination with Listview functionality.

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

# app/urls.py

from django.urls import path

from .views import *

urlpatterns = [
    path('list', EmployeeList.as_view(), name="list_emp"),
]

The below code is to list all employee details with the Django search view and how to write the logic for pagination in Django.

# app/views.py

from django.views import View
from django.shortcuts import render, redirect
from django.http import JsonResponse
from django.views.generic import TemplateView, ListView
from django.contrib import messages
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
from django.db.models import Q

from .forms import EmployeeForm
from .models import Employee


"""
    Purpose: List view for employees.
"""


class EmployeeList(ListView):
    template_name = 'app/list_view.html'

    def get(self, request, *args, **kwargs):
        """
        Return the list of all the active employee data.
        """
        search_filter = self.request.GET.get('filter')
        click = self.request.GET.get('click')
        sort_value = '-created_at'
        if click == '1':
            sort_value = self.request.GET.get('sortfn')
        if click == '2':
            sort_value = self.request.GET.get('sortln')
        if self.request.GET.get('click') == '3':
            sort_value = self.request.GET.get('sortemail')
        if self.request.GET.get('click') == '4':
            sort_value = self.request.GET.get('sortage')

        print(search_filter)
        if not search_filter:
            queryset = Employee.objects.filter(is_active=True).all().order_by(sort_value)
        else:
            queryset = Employee.objects.filter(Q(is_active=True) & (Q(firstName__icontains=search_filter) |
                                               Q(lastName__icontains=search_filter) |
                                               Q(email__icontains=search_filter) |
                                               Q(age__icontains=search_filter))).all().order_by(sort_value)

        paginator = Paginator(queryset, 5)
        try:
            page = int(request.GET.get('page', '1'))
        except:
            page = 1

        try:
            record_list = paginator.page(page)
        except PageNotAnInteger:
            record_list = paginator.page(1)
        except EmptyPage:
            record_list = paginator.page(paginator.num_pages)

            # Get the index of the current page
        index = record_list.number - 1

        # This value is maximum index of pages, so the last page - 1
        max_index = len(paginator.page_range)

        # range of 7, calculate where to slice the list
        start_index = index - 3 if index >= 3 else 0
        end_index = index + 4 if index <= max_index - 4 else max_index

        # new page range
        page_range = paginator.page_range[start_index:end_index]

        # showing first and last links in pagination
        if index >= 4:
            start_index = 1
        if end_index - index >= 4 and end_index != max_index:
            end_index = max_index
        else:

            end_index = None

        return render(request, self.template_name,
                      {'record_list': record_list, 'page_range': page_range, 'start_index': start_index,
                       'end_index': end_index, 'max_index': max_index})

HTML Code for List view and Django search and pagination feature.

# templates/app/list_view.html

<table class="table responsive datatable dataTable" id="sort" style="width:100%" >
  <thead class="thead-dark">
    <tr>
      <th scope="col" class="sorting fn">First Name</th>
      <th scope="col" class="sorting ln">Last Name</th>
      <th scope="col" class="sorting email">Email</th>
      <th scope="col" class="sorting age">Age</th>
      <th scope="col">Action</th>
    </tr>
  </thead>
  <tbody>
    {% if record_list %}
        {% for each in record_list %}
            <tr>
              <td>{{ each.firstName | capfirst }}</td>
              <td>{{ each.lastName | capfirst  }}</td>
              <td>{{ each.email }}</td>
              <td>{{ each.age }}</td>
              <td>
                  <a class="btn btn-primary" href="{% url 'edit_emp' each.id %}">
                      <i aria-hidden="true" class="fa fa-pencil-square-o"></i>
                  </a>

                  <a class="btn btn-danger" href="#" onclick="javascript:showdelete('{{ each.firstName }}','{{ each.id }}');">
                      <i aria-hidden="true" class="fa fa-trash"></i>
                  </a>
              </td>
            </tr>
        {% endfor %}
    {% else %}
        <tr>
            <th>No Data Found</th>
        </tr>
    {% endif %}
  </tbody>
</table>

<!-- Pagination -->
{% if record_list.has_other_pages %}

<div class="text-center" style="float:right">
    <ul class="pagination">

        {% if record_list.has_previous %}
        <li>

            <a class="previous" href="?page=1">
                << </a> <a class="previous" href="?page={{ record_list.previous_page_number }}">
                    < </a> </li> {% else %} <li class="disabled"><span>
                            << </span> </li> <li class="disabled"><span>
                                    < </span> </li> {% endif %} {% if start_index %} <li>
                                        <a class="next" href="?page={{ start_index }}">{{ start_index }}</a>

        </li>

        <li class="disabled"><span>&mldr;</span></li>
        {% endif %}

        {% for i in page_range %}
        {% if record_list.number == i %}
        <li class="active"><span>{{ i }} <span class="sr-only">(current)</span></span></li>
        {% else %}
        <li>
            <a class="previous" href="?page={{ i }}">{{ i }}</a>

        </li>
        {% endif %}
        {% endfor %}
        {% if record_list.has_next %}
        {% if end_index %}
        <li class="disabled"><span>&mldr;</span></li>
        <li><a class="previous" href="?page={{ end_index }}">{{ end_index }}</a></li>

        {% endif %}
        <li>
            <a class="next" href="?page={{ record_list.next_page_number }}"> > </a>
            <a class="next" href="?page={{max_index}}"> >> </a>

        </li>
        {% else %}
        <li class="disabled"><span> > </span></li>
        <li class="disabled"><span> >> </span></li>
        {% endif %}

    </ul>
</div>
<link rel="stylesheet" href="https://cdn.datatables.net/1.10.21/css/jquery.dataTables.min.css" crossorigin="anonymous">
<script src="https://cdn.datatables.net/1.10.21/js/jquery.dataTables.min.js"></script>

{% endif %}
<!--Pagination-->

Add the below js file in app/static/js folder.

# app/static/js/emp.js

$(function(){
    $('.alert').delay(3000).fadeOut();
    $('#delete_success').delay(3000).fadeOut();
    $("input[name=filter]").on('keyup keypress', function(e) {
        var keyCode = e.keyCode || e.which;
        if (keyCode === 13) {
        e.preventDefault();
        return false;
        }
     });
    $(".search").keyup(function(){
		var url = '/list'; // Backend url
		var params = {'filter':$("input[name=filter]").val(), 'sortfn':$("input[name=sortfn]").val(), 'sortln':$("input[name=sortln]").val(), 'sortemail':$("input[name=sortemail]").val(), 'sortage':$("input[name=sortage]").val(), 'click':$("input[name=click]").val()}; // Search field value
		fetchData(url, params); // Backend call for filtered data
	}).trigger('keyup');
});

function fetchData(url, params) {

    var sortbyfn = $("#sortbyfn").val();
    var sortbyln = $("#sortbyln").val();
    var sortbyemail = $("#sortbyemail").val();
    var sortbyage = $("#sortbyage").val();
    $.get(url, params)
    .done(function(data){
        // Put the data into target div
        $("#results").html(data);
        var sortbyfn = $("#sortbyfn").val();
           sortbycharfn=sortbyfn.substring(0,1)
           sortbycharln=sortbyln.substring(0,1)
           sortbycharemail=sortbyemail.substring(0,1)
           sortbycharage=sortbyage.substring(0,1)

           if(sortbycharfn =="-")
           {
                $(".fn").removeClass("main");
           }
           else
           {
                $(".fn").toggleClass("main");
           }
           if(sortbycharln =="-")
           {
                $(".ln").removeClass("main");
           }
           else
           {
                $(".ln").toggleClass("main");
           }
           if(sortbycharemail =="-")
           {
                $(".email").removeClass("main");
           }
           else
           {
                $(".email").toggleClass("main");
           }
           if(sortbycharage =="-")
           {
                $(".age").removeClass("main");
           }
           else
           {
                $(".age").toggleClass("main");
           }

		    $(".fn").click(function(){
              $(".fn").toggleClass("main");
               var sortbyfn = $("#sortbyfn").val();
               var click = $("#click").val(1);
               sortbycharfn=sortbyfn.substring(0,1)
               if(sortbycharfn =="-")
               {
                    sortbyfn=sortbyfn.substring(1);
                    $("#sortbyfn").val(sortbyfn);
                    $("#click").val(1);
               }
               else
               {
                 sortbyfn ="-"+sortbyfn;
                 $("#sortbyfn").val(sortbyfn);
                 $("#click").val(1);
               }
               var url = '/list';
               var params = {'filter':$("input[name=filter]").val(),'sortfn':$("input[name=sortfn]").val(),'sortln':$("input[name=sortln]").val(), 'sortemail':$("input[name=sortemail]").val(), 'sortage':$("input[name=sortage]").val(), 'click':$("input[name=click]").val()};
               fetchData(url, params);

            });
            $(".ln").click(function(){
              $(".ln").toggleClass("main");
               var sortbyln = $("#sortbyln").val();
               sortbycharln=sortbyln.substring(0,1)
               if(sortbycharln =="-")
               {
                    sortbyln=sortbyln.substring(1);
                    $("#sortbyln").val(sortbyln);
                    $("#click").val(2);
               }
               else{
                sortbyln ="-"+sortbyln;
                 $("#sortbyln").val(sortbyln);
                 $("#click").val(2);
               }
               var url = '/list'; // Backend url
               var params = {'filter':$("input[name=filter]").val(),'sortfn':$("input[name=sortfn]").val(),'sortln':$("input[name=sortln]").val(), 'sortemail':$("input[name=sortemail]").val(), 'sortage':$("input[name=sortage]").val(), 'click':$("input[name=click]").val()}; // Search field value
               fetchData(url, params);

            });
            $(".email").click(function(){
              $(".email").toggleClass("main");
               var sortbyemail = $("#sortbyemail").val();
               sortbycharemail=sortbyemail.substring(0,1)
               if(sortbycharemail =="-")
               {
                    sortbyemail=sortbyemail.substring(1);
                    $("#sortbyemail").val(sortbyemail);
                    $("#click").val(3);
               }
               else{
                sortbyemail ="-"+sortbyemail;
                 $("#sortbyemail").val(sortbyemail);
                 $("#click").val(3);
               }
               var url = '/list'; // Backend url
               var params = {'filter':$("input[name=filter]").val(),'sortfn':$("input[name=sortfn]").val(),'sortln':$("input[name=sortln]").val(), 'sortemail':$("input[name=sortemail]").val(), 'click':$("input[name=click]").val()}; // Search field value
               fetchData(url, params);

            });
            $(".age").click(function(){
              $(".lagen").toggleClass("main");
               var sortbyage = $("#sortbyage").val();
               sortbycharage=sortbyage.substring(0,1)
               if(sortbycharage =="-")
               {
                    sortbyage=sortbyage.substring(1);
                    $("#sortbyage").val(sortbyage);
                    $("#click").val(4);
               }
               else{
                sortbyage ="-"+sortbyage;
                 $("#sortbyage").val(sortbyage);
                 $("#click").val(4);
               }
               var url = '/list'; // Backend url
               var params = {'filter':$("input[name=filter]").val(),'sortfn':$("input[name=sortfn]").val(),'sortln':$("input[name=sortln]").val(), 'sortemail':$("input[name=sortemail]").val(), 'sortage':$("input[name=sortage]").val(), 'click':$("input[name=click]").val()}; // Search field value
               fetchData(url, params);

            });
        // Get next page on navigation button click
        $(".previous, .next").click(function(elem){
            // Prevent button from taking you away from current page
            elem.preventDefault();
            // Get the page's url from the button clicked
            var url = '/list' + $(this).attr('href');

            // Call this function again with url containing page parameter
            fetchData(url, params);
        });
    });
};

Rendered HTML For ListView and Pagination

Django pagination bootstrap

Rendered HTML for Django search box

Django search filter

Create View

Now we will use the Create View Function to create Employee Details.

Below code to add URL for creating employee details.

# app/urls.py

from django.urls import path

from .views import *

urlpatterns = [
    path('add', EmployeeAdd.as_view(), name="add_emp"),
]

Views for Create Operation.

# app/views.py

class EmployeeAdd(View):
    """
        This class will covers the create and list view of employee.
    """
    form_class = EmployeeForm
    template_name = 'app/add_view.html'

    def get(self, request):
        return render(request, self.template_name, {'form': self.form_class})

    def post(self, request, *args, **kwargs):
        """
        Create a new employee instance.
        :param request:
        :param args:
        :param kwargs:
        :return: Return status as 200 if form is valid else it will return status as 400 if data is invalid.
        """

        form = self.form_class(request.POST)
        queryset = Employee.objects.filter(is_active=True).all()

        if form.is_valid():
            data = form.save(commit=False)
            data.save()

            messages.add_message(request, messages.SUCCESS, 'Data Added Successfully')
            return redirect('/')
        print(form.errors)
        return render(request, self.template_name,
                      {'form': form, 'record_list': queryset, 'ValidationError': form}, status=400)

Let’s write a code for the Form validation. Add the below code in app/forms.py file.

# app/forms.py

from django import forms
from .models import Employee


class EmployeeForm(forms.ModelForm):
    id = forms.IntegerField(required=False, widget=forms.HiddenInput())
    firstName = forms.CharField(widget=forms.TextInput(attrs={'class': 'form-control'}))
    lastName = forms.CharField(widget=forms.TextInput(attrs={'class': 'form-control'}))
    email = forms.CharField(widget=forms.TextInput(attrs={'class': 'form-control'}))
    age = forms.IntegerField(widget=forms.NumberInput(attrs={'class': 'form-control'}))

    class Meta:
        model = Employee
        fields = ['firstName', 'lastName', 'email', 'age', 'id']

    def clean(self):
        cleaned_data = super(EmployeeForm, self).clean()
        email = cleaned_data.get('email', None)
        id = cleaned_data.get('id', None)
        if not email:
            return cleaned_data
        check_ip_exist = Employee.objects.filter(email=email, is_active=1)
        if id:
            check_ip_exist = Employee.objects.filter(email=email, is_active=1).exclude(id=id)
            if check_ip_exist:
                raise forms.ValidationError('Entered Email field is already exist!')
        else:
            if check_ip_exist:
                raise forms.ValidationError('Entered Email field is already exist!')
        return cleaned_data

Html Code For Create View.

# templates/app/add_view.html

{% extends 'base.html' %}

{% block content %}
<style>
.errorlist {
    list-style:none;
    color: #1e1f1e;
    background-color: #f17070;
    border-color: #d6e9c6;
    padding: 15px;
    margin-bottom: 20px;
    border: 1px solid transparent;
    border-radius: 4px;
}

</style>
<div class="container pt-5">
    <h1> Add New Employee </h1>
    <br/>
    {% if form.errors %}
    {{form.non_field_errors}}
    {% endif %}
    <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 |striptags}}</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>
<script src="https://code.jquery.com/jquery-3.4.1.min.js"></script>
<script>
$( document ).ready(function() {
  $('.errorlist').delay(3000).fadeOut();
});
</script>
{% endblock %}

Rendered HTML

Rendered HTML with validation

Update View

Let’s write the code for the Update View.

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

# app/urls.py

from django.urls import path

from .views import *

urlpatterns = [

    path('edit/<int:pk>', EmployeeUpdate.as_view(), name="edit_emp"),
]

Below is the code for the Update view.

# app/views.py

class EmployeeUpdate(View):
    """
        This class will covers the update view of employee.
    """
    form_class = EmployeeForm
    template_name = 'app/edit_view.html'

    def get(self, request, pk):
        """
        Get employee data by pk.
        :param request:
        :param pk:
        :return: Return status as 200 if form is valid else it will return status as 400 if data is invalid.
        """

        emp_data = Employee.objects.filter(id=pk, is_active=True).first()
        if emp_data:
            return render(request, self.template_name, {'form': emp_data}, status=200)
        return render(request, self.template_name, status=400)

    def post(self, request, pk):
        """
        Update new employee instance.
        :param request:
        :param pk:
        :return: Return status as 200 if form is valid else it will return status as 400 if data is invalid.
        """
        form = self.form_class(request.POST)
        print(request.POST)
        first_name = form.data.get('firstName')
        last_name = form.data.get('lastName')
        email = form.data.get('email')
        age = form.data.get('age')
        queryset = Employee.objects.filter(is_active=True).all()

        if form.is_valid():
            Employee.objects.filter(id=pk).update(firstName=first_name, lastName=last_name, email=email, age=age)

            messages.add_message(request, messages.SUCCESS, 'Employee details Updated Successfully')
            return redirect('/')
        return render(request, self.template_name,
                      {'form': form.data, 'record_list': queryset, 'ValidationError': form}, status=400)

HTML template for update view.

# templates/app/edit_view.html

{% extends 'base.html' %}

{% block content %}
<style>
.errorlist {
    list-style:none;
    color: #1e1f1e;
    background-color: #f17070;
    border-color: #d6e9c6;
    padding: 15px;
    margin-bottom: 20px;
    border: 1px solid transparent;
    border-radius: 4px;
}

</style>

<div class="container pt-5">
    <h1> Update Post </h1>
    <br/>
    {% if ValidationError.errors %}
    {{ValidationError.non_field_errors}}
    {% endif %}
    <form method="post" novalidate>
        {% csrf_token %}
        <input type="hidden" name="id" class="form-control" required="" id="id_id" value="{{form.id}}">
        <div class="form-group">
            <label>First Name</label>
            <input type="text" name="firstName" class="form-control" required="" id="id_firstName" value="{{form.firstName}}">
            <span class="help-block" style="color:red">{{ValidationError.errors.firstName | striptags}}</span>
        </div>
        <div class="form-group">
            <label>Last Name</label>
            <input type="text" name="lastName" class="form-control" required="" id="id_lastName" value="{{form.lastName}}">
            <span class="help-block" style="color:red">{{ValidationError.errors.lastName | striptags}}</span>
        </div>
        <div class="form-group">
            <label>Email</label>
            <input type="text" name="email" class="form-control" required="" id="id_email" value="{{form.email}}">
            <span class="help-block" style="color:red">{{ValidationError.errors.email | striptags}}</span>
        </div>
        <div class="form-group">
            <label>Age</label>
            <input type="text" name="age" class="form-control" required="" id="id_age" value="{{form.age}}">
            <span class="help-block" style="color:red">{{ValidationError.errors.age | striptags}}</span>
        </div>
         <input type="hidden" name="id"  value="{{form.id}}">

        <div>
            <button type="submit" class="btn btn-success">Submit</button>
            <a href="{% url 'home' %}" class="btn btn-default">Cancel</a>
        </div>
    </form>
</div>
<script src="https://code.jquery.com/jquery-3.4.1.min.js"></script>
<script>
$( document ).ready(function() {
  $('.errorlist').delay(3000).fadeOut();
});
</script>
{% endblock %}

Rendered HTML

Rendered HTML with validation

Delete View

Add below code in app/urls.py

# app/urls.py

from django.urls import path

from .views import *

urlpatterns = [

    path('delete/<int:pk>', EmployeeDelete.as_view(), name="delete_emp"),
]

Code for Employee delete view.

# app/views.py

class EmployeeDelete(View):
    """
        This class will covers the delete view of users.
    """

    def get(self, request, pk):
        """
        This method will deactivate the passed user_id.
        :param request:
        :param pk: Instance pk
        :return: Return status as 200 if is_activate gets update successfully as False else it will
                return status as 400 if there is any
        """

        data = {}
        inactive_user = Employee.objects.filter(id=pk).update(is_active=False)
        if inactive_user:
            data['message'] = 1
        else:
            data['message'] = 0

        return JsonResponse(data)

HTML Template for Delete view.

# templates/app/delete_view.html

{% extends 'base.html' %}

{% block content %}

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

{% endblock %}

Delete Ajax Call

# app/static/js/emp.js

function showdelete(name,id)
{
    $('#autoid').val(id);
    $('#deleting_field').html(name);
    $('#myModal').modal('show');
}

function deleteemp()
{
    var deleteid= $('#autoid').val();
    url='/delete/'+deleteid;
    $.ajax({
            type: 'GET',
            url:url,
            dataType: 'json',

            success: function(data) {

            if(data.message ==0)
            {
                alert('Something Went Wrong');
            }
            else
            {
                $('#myModal').modal('hide');
                $("#delete_success").show();
                $('#delete_success').delay(3000).fadeOut();

               $("input[name=filter]").keyup(function(){
                    var url = '/list';
                    var params = {'filter':$("input[name=filter]").val()};
                    fetchData(url, params);
               }).trigger('keyup');
            }
            },
            error: function(data) { // if error occured
                alert("Error occured.please try again");
            }
    });
}

Rendered HTML

Here we are done with all the steps of Django search and pagination with CRUD functionality.

I hope you understand all the steps which I have covered in this blog which is based on Django search and pagination. If still you have any query do comment below.

Refer to the Git source code for the Django search and pagination project.

https://github.com/pranalikambli/django_crud_with_pagination_search.git

thank you

Leave a Comment