Tech Incent
Django

How to work with django ajax requests ?

django ajax request

You saw in the web application. Clicking a button, data save/load in content without reloading pages. That’s ajax. Ajax stands for Asynconic Javascript XMLHttpRequest. The purpose of using ajax makes save and load data without loading the entire page.

So there are many scenarios where are you use ajax in the Django application. Ajax makes the data load faster and simply post data.
So in this tutorial, we learn jquery ajax for the Django application to register the new users but it can be used in other form submissions or request JSON data. We follow this line…

Create a registration Form

Make and edit forms.py file for registration form

from django import forms
from django.contrib.auth.models import User

class UserRegistrationForm(forms.ModelForm):
    password1 = forms.CharField(
        label='Password',
        widget=forms.PasswordInput(attrs={'placeholder': 'Password'})
    )
    password2 = forms.CharField(
        label='Password confirmation',
        widget=forms.PasswordInput(attrs={'placeholder': 'Re-Enter Password'})
    )
    class Meta:
        model = User
        fields = ['first_name', 'last_name', 'email', 'username']
    
    def save(self, commit=True):
        # Save the provided password in hashed format
        user = super(UserRegistrationForm, self).save(commit=False)
        password = self.cleaned_data["password1"]
        user.set_password(password)
        if commit:
            user.save()
        return user

Create register views

Edit views.py file

Function Base View

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

from .forms import UserRegistrationForm

def registration_form_view(request):
    form = UserRegistrationForm(request.POST or None)

    if request.method == 'POST':
        if form.is_valid():
            form.save()
            if request.is_ajax():
                return JsonResponse({'success': True}, status=201)
            return redirect(reverse('home'))
        else:
            if request.is_ajax():
                return JsonResponse({'success': False, 'errors': form.errors}, status=406)
    return render(request, 'register_form.html', {'form': form})

Class Base View

from django.shortcuts import render, redirect, reverse
from django.http.response import JsonResponse
from django.views.generic import CreateView

from .forms import UserRegistrationForm

class RegistrationClassBaseView(CreateView):
    """ class Base register view, handle with ajax or none ajax"""
    template_name = 'register_form.html'
    form_class = UserRegistrationForm

    def form_valid(self, form):
        instance = form.save(commit=False)
        # other staff
        instance.save()
        if request.is_ajax():
            return JsonResponse({'success': True}, status=201)
        return redirect(reverse('home'))

    def form_invalid(self, form):
        if self.request.is_ajax():
            return JsonResponse({'success': False, 'errors': form.errors}, status=400)
        return super().form_invalid(form)

This view work on both nono ajax, and ajax request

Add this registration views to the router

Add urls.py and edit it with …

from django.urls import path

from .views import registration_form_view, RegistrationClassBaseView


urlpatterns = [
    path('signup', registration_form_view, name='register_view')
    path('signup-classbase', RegistrationClassBaseView.as_view(), name='class_base_register_view')
]

Setup base.html templates

Initial Template base template file with base.py

<!doctype html>
<html lang="en">
  <head>    
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">

    <!-- optional Bootstrap CSS -->
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/css/bootstrap.min.css" integrity="sha384-9aIt2nRpC12Uk9gS9baDl411NQApFmC26EwAOH8WgZl5MYYxFfc+NcPb1dKGj7Sk" crossorigin="anonymous">
    <title>Hello, world!</title>
    {% block css %}
    {% endblock %}
  </head>
  <body>
    {% block content %}
    {% endblock %}
    <!-- jQuery is medetory for Ajax request -->
    <script src="https://code.jquery.com/jquery-3.5.1.min.js" integrity="sha256-9/aliU8dGd2tb6OSsuzixeV4y/faTqgFtohetphbbj0=" crossorigin="anonymous"></script>
    <!-- Optional bootstrap and popper -->
    <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/umd/popper.min.js" integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo" crossorigin="anonymous"></script>
    <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/js/bootstrap.min.js" integrity="sha384-OgVRvuATP1z7JjHLkuOU7Xw704+h835Lr+6QL9UvYjZE3Ipu6Tp75j7Bh/kR0JKI" crossorigin="anonymous"></script>
    {% block js %}
    {% endblock %}
</body>
</html>

Jquery file is mandatory for jquery ajax requests. we are using bootstrap but it’s optional for $.ajax.

So I declare “{% block js %}”. it helps to render javascript code on every page. Learn more about extends templates

Create register_form.html templates and ajax code in the template

What is going on register_form.html file?

Explain: First of all I extend the base.html file. than declare form in Block Content. then we add Javascript AJAX jquery code in Block js. This ajax requires Jquery. Make sure you $.ajax code render under jquery file.

{% extends 'base.html' %}

{% block content %}
<div class="container mt-5">
    <form id="signup_form" action="{% url 'register_view' %}" method="post">
        {% csrf_token %}
        {% for error in form.non_field_errors %}
        <div class="alert alert-danger" role="alert"> {{ error }}</div>
        {% endfor %}
        {{ form.as_p }}
        <button>Submit</button>
    </form>
</div>
{% endblock %}

{% block js %}
<script>
    (function($) {
        let signUpForm = $('#signup_form');
        signUpForm.on('submit', function(e) {
            e.preventDefault();
            let $this = $(this);
            let method = $this.attr('method');
            let endpoint = $(this).attr('action');
            let data = $this.serialize();
            $.ajax({
                method: method,
                url: endpoint,
                data: data,
                success: function(resonse) {
                    console.log(resonse)
                    if (resonse.success){
                        signUpForm[0].reset()
                        alert('succesfully registered')
                    } else{
                        alert('data not valid registered')
                    }
                },
                error: function({responseText}) {
                    console.log(responseText)
                    alert('form data not vaild')
                }
            })
        })
    }(jQuery));
</script>
{% endblock %}

Browse application and test ajax

function base and class view output same

01. browse function base view http://127.0.0.1:8000/signup

02. browse class base view  http://127.0.0.1:8000/signup-classbase

03. Make an invalid form ajax submission

ajax-error
Invalid form ajax submit

04. Make a valid form ajax submission

ajax-success
Valid form ajax submit

Ajax get request

01. create an API user view

from django.core import serializers
from django.http.response import JsonResponse
from django.contrib.auth import get_user_model
def user_list_view(request):
    """ get json data """
    users = serializers.serialize(
        'json', 
        get_user_model().objects.all(), 
        fields=('first_name','last_name', 'username', 'email')
    )
    return JsonResponse({'users': users}, status=200)

02. Add routing user_list_view form

from django.urls import path
from .views import registration_form_view, RegistrationClassBaseView, user_list_view
urlpatterns = [
    path('signup', registration_form_view, name='register_view'),
    path('signup-classbase', RegistrationClassBaseView.as_view(), name='class_base_register_view'),
    path('ajax/users', user_list_view, name='json_user_list')

03. Test APIBrowse http://127.0.0.1:8000/ajax/users

04. Make Ajax request

$.ajax({
    method: 'get',
    url: "{% url 'json_user_list' %}",
    success: function({users}) {
        console.log(users)
    },
    error: function(err){
        console.log(err)
    }
})

Checkout tutorial source code

https://github.com/techincent/django-snippets

Related posts

Understanding Django and django design principles

Tech Incent

Explained Django inline formset factory with example?

Sajal Mia

How to set up django react together ?

Sajal Mia