Django
CRUD with Django and Ajax

CRUD with Django and Ajax

In this post we will learn to CRUD with Django and Ajax. Ajax will help to submit the Django forms without the page being refreshed. We will also learn to display, edit and delete content with refreshing the page.

Table of Contents

Initial Setup

#terminal
mkdir Django_Crud_Ajax
cd Django_Crud_Ajax
python3 -m venv venv
source venv/bin/activate
gh repo create
#then walk through
#Terminal
cd Django_Crud_With_Ajax
#Install django
pip install django
django-admin startproject Django_Crud_With_Ajax
cd Django_Crud_With_Ajax
python manage.py runserver

Question_Answer_app

#terminal
python manage.py startapp Question_Answer_app
#open vs code with 
code .

Create a Model

Add the following lines of code to the models.py file of Question_Answer_app

from django.db import models

# Create your models here.
class QuestionsAnswer(models.Model):
    question = models.TextField()
    answer = models.TextField()


    def __str__(self):
        return self.question

Add the application to the django project “Django_Crud_With_Ajax” by editing the settings.py file.

.................................
# Application definition

INSTALLED_APPS = [
    'Question_Answer_app',
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
]
...................................

Make migrations and migrate

#terminal
python manage.py makemigrations
python manage.py migrate

SuperAdmin

#terminal
python manage.py createsuperuser

To add model to admin edit the admin.py as follow.

from django.contrib import admin
from .models import QuestionsAnswer

# Register your models here.
@admin.register(QuestionsAnswer)
class QuestionAdmin(admin.ModelAdmin):
    list_display = ('id','question','answer')

Run the server and visit http://127.0.0.1:8000/admin/

Login with your superuser credentials

Add a question and an answer.

Create the Form

Create a new forms.py within your app and fill it with the following code.

from django import forms
from .models import QuestionsAnswer

class QuestionForm(forms.ModelForm):
    class Meta:
        model = QuestionsAnswer
        fields = ['question','answer']

Create views and urls to display the form and data

Edit the views.py file of your application as follow.

from django.shortcuts import render,redirect

from .models import QuestionsAnswer
from .forms import QuestionForm

# Create your views here.

def home(request):
    all_questions = QuestionsAnswer.objects.all()
    if request.method == 'POST':
        form = QuestionForm(request.POST)
        if form.is_valid():
            form.save()
            print("Form submitted")

            return redirect('home')
    else:
        form = QuestionForm()

    data = {'form':form,'questions':all_questions}
    return render(request,"home.html",data)

Edit the urls.py of your django-project as follows.

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

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

Create the urls.py file in your application and add the following line of code.

from django.urls import path
from .import views

urlpatterns = [
    path("",views.home,name="home"),
]

Templates for home

Create a folder named templates within your application. Within the template folder create file name “home.html”.

Add following lines of code to home.html.

<!DOCTYPE html>
<html>
    <head>
        <title>
            This is home page
        </title>

    </head>
    <body>
        <form action="" method="post">
            {% csrf_token %}
            {{form.as_p}}
            
            <button type="submit">Submit</button>
        </form>

        <ul id="que-list">
            {% for q in questions %}
                <li>
                    <h3>
                        {{q.question}}
                    </h3>
                    <p>
                        {{q.answer}}
                    </p>
                    <input type="button" data-qid="{{q.id}}"
                    class="btn-edit" value="Edit"/>
                    <input type="button" data-qid="{{q.id}}"
                    class="btn-del"
                    value="Delete"/>
                </li>

            {% endfor %}
        </ul>
    </body>
</html>

So, far we can submit the form but our page reloads after we submit the form. We want to submit the form and show the latest content without reloading the page. For this we will be using AJAX.

Create and Read with Ajax

Change the templates/home.html as follow.

{% load static %}
<!DOCTYPE html>
<html>
    <head>
        <title>
            This is home page
        </title>
        <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
        
        </script>

    </head>
    <body>
        <form action="" method="post">
            {% csrf_token %}
            {{form.as_p}}
            
            <button type="submit" id="btnsave">Submit</button>
            
        </form>

        <ul id="que-list">
            {% for q in questions %}
                <li>
                    <h3>
                        {{q.question}}
                    </h3>
                    <p>
                        {{q.answer}}
                    </p>
                    <input type="button" data-qid="{{q.id}}"
                    class="btn-edit" value="Edit"/>
                    <input type="button" data-qid="{{q.id}}"
                    class="btn-del"
                    value="Delete"/>
                </li>

            {% endfor %}
        </ul>
        
        <script>
            $("#btnsave").click(function(){
                console.log("Save button clicked");
            });
        </script>

    </body>
</html>

Edit the views.py

from django.shortcuts import render,redirect
from django.http import JsonResponse

from .models import QuestionsAnswer
from .forms import QuestionForm

# Create your views here.

def home(request):
    form = QuestionForm()
    all_questions = QuestionsAnswer.objects.all()
    data = {'form':form,'questions':all_questions}
    return render(request,"home.html",data)

def save_data(request):
    if request.method == "POST":
        form = QuestionForm(request.POST)
        if form.is_valid():
            que = request.POST['question']
            ans = request.POST['answer']

            question = QuestionsAnswer(question=que,answer=ans)

            question.save()

            question_data = list(QuestionsAnswer.objects.values())

            return JsonResponse({"status":'Save','question_data':question_data})
        
        else:
            return JsonResponse({'status':0})

edit application level urls.py

from django.urls import path

from .import views

urlpatterns = [
    path("",views.home,name="home"),
    path("save/",views.save_data,name="save"),
]

Output so Far

Add more code to home.html

  <script>
            $("#btnsave").click(function(){
                console.log("Save button clicked");
                output = "";
                let que = $("#id_question").val();
                let ans = $("#id_answer").val();
                let csr = $("input[name=csrfmiddlewaretoken]").val();

                que_data = {question:que, answer:ans,csrfmiddlewaretoken:csr}

                console.log(que_data);
                console.log(csr);


            });
        </script>

Adding AJAX

 <script>
            $("#btnsave").click(function(){
                console.log("Save button clicked");
                output = "";
                let que = $("#id_question").val();
                let ans = $("#id_answer").val();
                let csr = $("input[name=csrfmiddlewaretoken]").val();

                que_data = {question:que, answer:ans,csrfmiddlewaretoken:csr}

                console.log(que_data);
                console.log(csr);

                $.ajax({
                    url:"{% url 'save' %}",
                    method:"POST",
                    data:que_data,
                    dataType:"json",

                    success:function(data){
                        console.log("data saved");
                        x = data.question_data
                    console.log(x.length);

                    if(data.status == 'Save'){
                        console.log("data saved again");
                        for(i=0; i<x.length;i++){
                            console.log(x[i].question);
                            output += '<li><h3>' + x[i].question + '</h3><p>'+x[i].answer+'</p></li><input type="button" class="btn btn-edit" value="Edit" data-sid='+x[i].id+"><input type='button' class='btn btn-del' value='Delete' data-sid="+x[i].id+">"
                        }
                        $("#que-list").html(output) ;
                      
                        $("form")[0].reset();
                        location.reload();
                    }

                    if(data.status ==0){
                        console.log("Unable to save form");
                        
                        $("form")[0].reset();
                        location.reload();
                    
                    }
                    }
                });


            });
        </script>

Now the data will be added with the page being reloaded.

Deleting the Entries with help of AJAX

Add the following code to home.html

<script>

            //create
            $("#btnsave").click(function(){
                console.log("Save button clicked");
                output = "";
                let que = $("#id_question").val();
                let ans = $("#id_answer").val();
                let csr = $("input[name=csrfmiddlewaretoken]").val();

                que_data = {question:que, answer:ans,csrfmiddlewaretoken:csr}

                console.log(que_data);
                console.log(csr);

                $.ajax({
                    url:"{% url 'save' %}",
                    method:"POST",
                    data:que_data,
                    dataType:"json",

                    success:function(data){
                        console.log("data saved");
                        x = data.question_data
                    console.log(x.length);

                    if(data.status == 'Save'){
                        console.log("data saved again");
                        for(i=0; i<x.length;i++){
                            console.log(x[i].question);
                            output += '<li><h3>' + x[i].question + '</h3><p>'+x[i].answer+'</p></li><input type="button" class="btn btn-edit" value="Edit" data-sid='+x[i].id+"><input type='button' class='btn btn-del' value='Delete' data-sid="+x[i].id+">"
                        }
                        $("#que-list").html(output) ;
                      
                        $("form")[0].reset();
                        location.reload();
                    }

                    if(data.status ==0){
                        console.log("Unable to save form");
                        
                        $("form")[0].reset();
                        location.reload();
                    
                    }
                    }
                });


            });

           
        //delete data
        $(document).on("click",".btn-del",function(){
            console.log("Delete Button Clicked");
            let id = $(this).attr("data-qid");
            let csr = $("input[name=csrfmiddlewaretoken]").val();

            console.log(id);
            mydata = {qid:id,csrfmiddlewaretoken:csr};
            console.log(mydata);
            mythis = this;

            $.ajax({
                url:"{%url 'delete' %}",
                method:"POST",
                data:mydata,
                success:function(data){
                    if(data.status==1){
                        console.log("Data Deleted Successfully");
                        location.reload();
                    }
                    if(data.status == 0){
                        console.log("Unable to delete data");
                    }
                },
            });

        });

        </script>

Now add following function to views.py

#Delete Data
def delete_data(request):
    if request.method == "POST":
        id = request.POST.get("qid")
        pi = QuestionsAnswer.objects.get(pk=id)
        pi.delete()
        return JsonResponse({'status':1})
    else:
        return JsonResponse({'status':0})

And add the following code to urls.py

from django.urls import path
from .import views

urlpatterns = [
    path("",views.home,name="enroll"),
    path("save/",views.save_data,name="save"),
    path("delete/",views.delete_data,name="delete"),

]

Editing the content

First edit home.html form part as follow.

 <form action="" method="post">
            {% csrf_token %}
            <input type="hidden" name="queid" id="queid"/>
            {{form.as_p}}
            
            <button type="submit" id="btnsave">Submit</button>
            
        </form>

This highlighted part will help us to edit the content. Without this the edit content will be added to database as new content.

Now, add the following lines of code within <script> … </script> of the home.html.

<script>

     ................................................

        $(document).on('click','.btn-edit',function(){
            console.log("Edit button clicked");
            let id = $(this).attr("data-qid");
            let csr = $("input[name=csrfmiddlewaretoken]").val()

            console.log(id)
            mydata = {qid:id,csrfmiddlewaretoken:csr};
            console.log(mydata);

            $.ajax({
                url:"{%url 'edit'%}",
                method:"POST",
                data:mydata,
                dataType:"json",
                success:function(data){
                    console.log(data);
                     $("#queid").val(data.id);
                     $("#id_question").val(data.question);
                     $("#id_answer").val(data.answer);

                },
            });
        });


        </script>

Add the following function to views.py

#Edit Data
def edit_data(request):
    if request.method == "POST":
        id = request.POST.get('qid')
        q = QuestionsAnswer.objects.get(pk=id)
        
        data = {"id":q.id,
                "question":q.question,
                "answer":q.answer}
        return JsonResponse(data)

Add following codes to urls.py file of the application.

from django.urls import path
from .import views

urlpatterns = [
    path("",views.home,name="enroll"),
    path("save/",views.save_data,name="save"),
    path("delete/",views.delete_data,name="delete"),
    path("edit/",views.edit_data,name="edit"),
]

The edited content is saved as the new entry. To deal with this we need to edit our save_data(request) function of views.py as follow.

def save_data(request):
    if request.method == 'POST':
        form = QuestionForm(request.POST)
        if form.is_valid():
            qid= request.POST.get('queid')
            print("******************")
            print(qid)
            que = request.POST['question']
            ans = request.POST['answer']

            #case when qid is empty, that is new entry
            if(qid==""):
                question = QuestionsAnswer(question=que,answer=ans)
            
            #case when qid is not empty, editing old entry
            else:
                question = QuestionsAnswer(id=qid,question=que,answer=ans)

            question.save()

            question_data = list(QuestionsAnswer.objects.values())

            return JsonResponse({'status':'Save','question_data':question_data})
        
        else:
            return JsonResponse({'status':0})

Now, edit the home.html code as follow.

<script>

            //create
            $("#btnsave").click(function(){
                console.log("Save button clicked");
                output = "";

                let quesid = $("#queid").val();
                let que = $("#id_question").val();
                let ans = $("#id_answer").val();
                let csr = $("input[name=csrfmiddlewaretoken]").val();

                que_data = {queid:quesid,question:que, answer:ans,csrfmiddlewaretoken:csr}

                console.log(que_data);
                console.log(csr);

                $.ajax({
                    url:"{% url 'save' %}",
                    method:"POST",
                    data:que_data,
                    dataType:"json",

                    success:function(data){
                        console.log("data saved");
                        x = data.question_data
                    console.log(x.length);

                    if(data.status == 'Save'){
                        console.log("data saved again");
                        for(i=0; i<x.length;i++){
                            console.log(x[i].question);
                            output += '<li><h3>' + x[i].question + '</h3><p>'+x[i].answer+'</p></li><input type="button" class="btn btn-edit" value="Edit" data-sid='+x[i].id+"><input type='button' class='btn btn-del' value='Delete' data-sid="+x[i].id+">"
                        }
                        $("#que-list").html(output) ;
                        $("#queid").val("");
                        $("form")[0].reset();
                        location.reload();
                    }

                    if(data.status ==0){
                        console.log("Unable to save form");
                        
                        $("form")[0].reset();
                        location.reload();
                    
                    }
                    }
                });


            });

           

The final output

Tags :