分享

Django AJAX : How to use AJAX in Django Template...

 只怕想不到 2021-12-10

AJAX or Asynchronous JavaScript And XML is a set of web development techniques using web technologies on the client-side to create asynchronous web requests.

In simpler words, AJAX allows web pages to be updated asynchronously by exchanging data with a web server behind the scenes. This means that updating parts of a web page is possible, without reloading the whole page.

We can make AJAX requests from Django templates using JQuery. With the jQuery AJAX methods, you can request text, HTML, XML, or JSON from a remote server using both HTTP Get and HTTP Post and you can load the external data directly into the selected HTML elements of your web page.

In this tutorial, we will learn how to make AJAX HTTP GET and POST requests from Django templates.

Pre-Requirements

I am assuming you have a basic working knowledge of Django. Therefore, I am not going into the project setup part in case you need help with that I recommend reading the following articles.

This is a very basic project with an app called AJAX and I am using bootstrap and Django crispy form for styling.

Github repo –https://github.com/TheAbhijeet/Django-with-JQuery-and-AJAX

Making AJAX GET requests with Django and JQuery

The HTTP GET method is used to retrieve data from the server.

In this section, we will create a signup page where we will check the availability of a username using JQuery and AJAX in Django templates. This is a very common requirement for most modern apps.

views.py

from django.contrib.auth.models import User from django.contrib.auth.decorators import login_required from django.http import JsonResponse from django.contrib.auth.forms import UserCreationForm from django.contrib.auth import login, authenticate from django.shortcuts import render, redirect from django.views.generic.edit import CreateView from django.urls import reverse_lazy @login_required def home(request): return render(request, 'home.html') class SignUpView(CreateView): template_name = 'signup.html' form_class = UserCreationForm success_url = reverse_lazy('home') def form_valid(self, form): valid = super().form_valid(form) login(self.request, self.object) return valid def validate_username(request): '''Check username availability''' username = request.GET.get('username', None) response = { 'is_taken': User.objects.filter(username__iexact=username).exists() } return JsonResponse(response)

So here we have three views first one is the home view which is basically rending a simple template.

Next is SignUpView inheriting from Django’s CreateView class to create users using Django’s builtin UserCreationForm class which provides a very basic form for user signup and on successful signup we are logging in the user and then redirecting them to the homepage.

Finally  validate_username view is our AJAX view which returns a JSON object with boolean from the username exists query.

The JsonResponse class returns an HTTP response with an application/json content type, converting the given object into a JSON object. So if the username already exists in the database it will return a JSON object as follows.

{ 'is_taken': true }

urls.py

from django.urls import path from .views import home, SignUpView, validate_username urlpatterns = [ path('', home, name='home'), path('signup', SignUpView.as_view(), name='signup'), path('validate_username', validate_username, name='validate_username') ]

home.html

<h1>Welcome, {{ user.username }}!</h1>

signup.html

{% load crispy_forms_tags %} <!DOCTYPE html> <html lang='en'> <head> <meta charset='UTF-8'> <meta name='viewport' content='width=device-width, initial-scale=1.0'> <link rel='stylesheet' href='https://stackpath./bootstrap/4.5.2/css/bootstrap.min.css' integrity='sha384-JcKb8q3iqJ61gNV9KGb8thSsNjpSL0n8PARn9HuZOnIxN0hoP+VmmDGMN5t9UJ0Z' > </head> <body> <div class='container mt-5 w-50'> <form id='signupForm' method='POST'> {% csrf_token %} {{ form|crispy }} <input type='submit' name='signupSubmit' class='btn btn-success btn-lg' /> </form> </div> {% block javascript %} <script src='https://ajax./ajax/libs/jquery/3.5.1/jquery.min.js'></script> <script> $(document).ready(function () { // catch the form's submit event $('#id_username').keyup(function () { // create an AJAX call $.ajax({ data: $(this).serialize(), // get the form data url: '{% url 'validate_username' %}', // on success success: function (response) { if (response.is_taken == true) { $('#id_username').removeClass('is-valid').addClass('is-invalid'); $('#id_username').after('<div class='invalid-feedback d-block' id='usernameError'>This username is not available!</div>') } else { $('#id_username').removeClass('is-invalid').addClass('is-valid'); $('#usernameError').remove(); } }, // on error error: function (response) { // alert the error if any error occured console.log(response.responseJSON.errors) } }); return false; }); }) </script> {% endblock javascript %} </body> </html>

Let’s breakdown the template is small pieces to understand better.

Inside the head tag, we are loading the bootstrap from CDN you can download the library and serve it from static folders as well.

<form id='signupForm' method='POST'>
            {% csrf_token %}
            {{ form|crispy  }}
<input type='submit' name='signupSubmit' class='btn btn-success btn-lg' />
</form>

Then we are rending the Django form using crispy tag for styling.

<script src='https://ajax./ajax/libs/jquery/3.5.1/jquery.min.js'></script>

Next, inside the javascript block, we are pulling JQuery from google CDN you can download it locally as well.

$(document).ready(function () {
    ( .... )
})

Then we have another script having ready method, The ready() method is used to make a function available after the document is loaded. The code written inside the $(document ).ready() method will run once the page DOM is ready to execute JavaScript code.

$('#id_username').keyup(function() { // create an AJAX call $.ajax({ data: $(this).serialize(), // get the form data url: '{% url 'validate_username' %}', // on success success: function(response) { if (response.is_taken == true) { $('#id_username').removeClass('is-valid').addClass('is-invalid'); $('#id_username').after('<div class='invalid-feedback d-block' id='usernameError'>This username is not available!</div>') } else { $('#id_username').removeClass('is-invalid').addClass('is-valid'); $('#usernameError').remove(); } }, // on error error: function(response) { // alert the error if any error occured console.log(response.responseJSON.errors) } }); return false; });

The AJAX method is triggered by keyup function it takes two parameters data and the URL  upon successful completion of requests one of either callback i.e success and error gets invoked. On a successful call, we have a conditional statement to add or remove the invalid class from the input form field and the return false at the end of the script prevents forms from submitting, therefore, preventing page reload.

Save the files and run the server you should see AJAX in action.

Making AJAX POST requests with Django and JQuery

The HTTP POST method is used to send data to the server.

In this section, we will learn how to make POST requests with JQuery and AJAX in Django templates.

We will create a contact form and save the data provided by the user into the database with JQuery and AJAX.

Making AJAX POST requests with Django

models.py

from django.db import models

class Contact(models.Model):
    name = models.CharField(max_length=100)
    email = models.EmailField()
    message = models.TextField()

    def __str__(self):
        return self.name

forms.py

from django import forms from .models import Contact class ContactForm(forms.ModelForm): class Meta: model = Contact fields = '__all__'

urls.py

from django.urls import path
from .views import contact_form

urlpatterns = [
   path('contact-form/', contact_form, name='contact_form')
]

views.py

from django.http import JsonResponse from django.shortcuts import render from .forms import ContactForm def contact_form(request): form = ContactForm() if request.method == 'POST' and request.is_ajax(): form = ContactForm(request.POST) if form.is_valid(): name = form.cleaned_data['name'] form.save() return JsonResponse({'name': name}, status=200) else: errors = form.errors.as_json() return JsonResponse({'errors': errors}, status=400) return render(request, 'contact.html', {'form': form})

In the view, we are verifying the ajax request with request.is_ajax() method then if the form is valid we are saving it to the database and returning JSON object with status code and name and for an invalid form, we are returning the form errors with status code 400 i.e bad request.

contact.html

{% load crispy_forms_tags %}

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

<head>
    <meta charset='UTF-8'>
    <meta name='viewport' content='width=device-width, initial-scale=1.0'>
    <title>Contact us</title>
    <link rel='stylesheet' href='https://stackpath./bootstrap/4.5.2/css/bootstrap.min.css'
        integrity='sha384-JcKb8q3iqJ61gNV9KGb8thSsNjpSL0n8PARn9HuZOnIxN0hoP+VmmDGMN5t9UJ0Z' >

</head>

<body>
    <div class='container mt-5 w-50'>
        <form id='contactForm' method='POST'>
            {% csrf_token %}
            {{ form|crispy  }}
            <input type='submit' name='contact-submit' class='btn btn-success btn-lg' />
        </form>
    </div>
    {% block javascript %}
    <script src='https://ajax./ajax/libs/jquery/3.5.1/jquery.min.js'></script>

    <script>
        $(document).ready(function () {
            // catch the form's submit event
            $('#contactForm').submit(function () {
                // create an AJAX call
                $.ajax({
                    data: $(this).serialize(), // get the form data
                    type: $(this).attr('method'), // GET or POST
                    url: '{% url 'contact_form' %}',
                    // on success
                    success: function (response) {
                        alert('Thankyou for reaching us out ' + response.name);
                    },
                    // on error
                    error: function (response) {
                        // alert the error if any error occured
                        alert(response.responseJSON.errors);
                        console.log(response.responseJSON.errors)
                    }
                });
                return false;
            });
        })
    </script>
    {% endblock javascript %}
</body>

</html>

Let’s break down the template in smaller modules to understand it better.

First, we are importing bootstrap inside the head tag from CDN then inside the body, we are reading the form with crispy tag for styling.

Then inside the javascript block first, we are loading JQuery from the CDN.

<script src='https://ajax./ajax/libs/jquery/3.5.1/jquery.min.js'></script>

Then Inside the $(document).ready()function we have our AJAX method.

$('#contactForm').submit(function() {
    // create an AJAX call
    $.ajax({
        data: $(this).serialize(), // get the form data
        type: $(this).attr('method'), // GET or POST
        url: '{% url 'contact_form' %}',
        // on success
        success: function(response) {
            alert('Thankyou for reaching us out ' + response.name);
        },
        // on error
        error: function(response) {
            // alert the error if any error occured
            alert(response.responseJSON.errors);
            console.log(response.responseJSON.errors)
        }
    });
    return false;
});

On form submit we are invoking the ajax method which is serializing the form data and sending it to the given URL. On a successful call, we are showing an alert dialog with a dynamic message based on the user name.

Making AJAX POST requests with Django and JQuery using Class-based views

views.py

from django.views.generic.edit import FormView from django.http import JsonResponse class ContactFormView(FormView): template_name = 'contact.html' form_class = ContactForm def form_valid(self, form): ''' If the form is valid return HTTP 200 status code along with name of the user ''' name = form.cleaned_data['name'] form.save() return JsonResponse({'name': name}, status=200) def form_invalid(self, form): ''' If the form is invalid return status 400 with the errors. ''' errors = form.errors.as_json() return JsonResponse({'errors': errors}, status=400)

We just need to return a JSON object from the form_valid() method of FormView, you can also use other generic class-based views by overriding post() method.

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约