Tech Incent
django

How to work with django ajax requests ?

django ajax request

You saw in a 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 Django application to register the new users but it can be used in other form submission 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 view 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 request. 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 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 and test ajax

function base and class view output same

  1. browse function base view http://127.0.0.1:8000/signup
  2. browse class base view  http://127.0.0.1:8000/signup-classbase
  • Make an invalid form ajax submission

    ajax-error

  • Make a valid form ajax submission

    ajax-success

Ajax get request

  1. 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)
  2. Add routing
    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')
    ]
  3. Test API
    Browse http://127.0.0.1:8000/ajax/users
  4. 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

How to setup django static and media file in aws s3 ?

Sajal Mia

How to deploy django and react in heroku ?

Tech Incent

Django Send Email with AWS Simple Email Service(SES)

Sajal Mia