DEV Community

Cover image for How to send Django form with AJAX
Rashid
Rashid

Posted on • Edited on

How to send Django form with AJAX

This post cross-published with OnePublish

What's up DEV Network?

In this quick tutorial I am going to show you how to POST Django form without refreshing page using AJAX.

I am assuming that you already created your project. Let's start with creating our very simple Post model in models.py

from django.db import models

class Post (models.Model):
    title = models.CharField(max_length=50)
    description = models.TextField()

    def __str__(self):
        return self.title

Enter fullscreen mode Exit fullscreen mode

Once you created open views.py and insert following code:

from django.shortcuts import render
from django.http import JsonResponse
from .models import Post

def create_post(request):
    posts = Post.objects.all()
    response_data = {}

    if request.POST.get('action') == 'post':
        title = request.POST.get('title')
        description = request.POST.get('description')

        response_data['title'] = title
        response_data['description'] = description

        Post.objects.create(
            title = title,
            description = description,
            )
        return JsonResponse(response_data)

    return render(request, 'create_post.html', {'posts':posts})        
Enter fullscreen mode Exit fullscreen mode

As you see we imported JsonResponse which is an HttpResponse subclass that helps to create a JSON-encoded response. It is default Content-Type header is set to application/json. The first parameter, data, should be a dict instance. We will use JSON data to display created post right away.

I highly recommend to take look following StackOverflow question to have a better understanding difference between request.POST[] and request.POST.get()

What is the difference between

request.POST.get('sth')

and

request.POST['sth']

Did not find the similar question, both work the same for me, suppose I can use them separately but maybe I am wrong, that is why I am asking. Any ideas?

If you have more than one form in your page you can separate them by using action, so your view will not get multiple requests at the same time.

To create and save an object in a single step, we are using the create() method.

Let's take a look our html form now

<form method="POST" id="post-form">
  {% csrf_token %}
  <div class="form-group">
    <label>Title</label>
    <input type="text" class="form-control" id="title" placeholder="Title">
  </div>
   <div class="form-group">
     <label>Description</label>
     <textarea class="form-control" id="description" placeholder="Description"></textarea>
   </div>
   <button type="submit" class="btn btn-primary">Submit</button>
</form>
Enter fullscreen mode Exit fullscreen mode

As you know we are using csrf_token to make post request and it is a just simple bootstrap form. We give id for each input to get values with AJAX by id.

$(document).on('submit', '#post-form',function(e){
    $.ajax({
        type:'POST',
        url:'{% url "create" %}',
        data:{
            title:$('#title').val(),
            description:$('#description').val(),
            csrfmiddlewaretoken:$('input[name=csrfmiddlewaretoken]').val(),
            action: 'post'
        },
        success:function(json){
            document.getElementById("post-form").reset();
            $(".posts").prepend('<div class="col-md-6">'+
                '<div class="row no-gutters border rounded overflow-hidden flex-md-row mb-4 shadow-sm h-md-250 position-relative">' +
                    '<div class="col p-4 d-flex flex-column position-static">' +
                        '<h3 class="mb-0">' + json.title + '</h3>' +
                        '<p class="mb-auto">' + json.description + '</p>' +
                    '</div>' +
                '</div>' +
            '</div>' 
            )
        },
        error : function(xhr,errmsg,err) {
        console.log(xhr.status + ": " + xhr.responseText); // provide a bit more info about the error to the console
    }
    });
});
Enter fullscreen mode Exit fullscreen mode

Note that you have to include jquery-2.2.4.min.js to your static files, you can take it from my git repository.

Alright! What is going on here? Initially, it is important to add id property to your form, so jQuery can detect form submission. AJAX type specifies the type of request which is post because we are sending data to database and url specifies the URL to send the request to. Then, we are using val() method to get the values of form elements by id and sending it with data parameter which specifies data to be sent to the server. It is necessary to get value of csrf_token otherwise it will cause 403 Forbidden error. As you see we specified action to let our view detect which form is submitting.

Once request successfully sent, we are cleaning form and appending our new post right away into the posts row.

The .prepend() method inserts the specified content as the first child of each element in the jQuery collection (To insert it as the last child, use .append()).

If some error occurs while sending request (I hope not😅) then the last function will add this error information to the console, so you can see what caused this nasty error. I guess you already know how to display error to user nicely.

At the end you will get following result

Mission Accomplished!

You just learned how to POST Django form using AJAX 🚀🚀

You can clone or download this project from my git repository and don't forget to follow and support me on twitter and instagram, join Reverse Astronauts community!👨‍🚀 See you next tutorial!

#django

Django is a high-level Python Web framework that encourages rapid development and clean, pragmatic design. Built by experienced developers, it takes care of much of the hassle of Web development, so you can focus on writing your app without needing to reinvent the wheel. It’s free and open source.

Top comments (7)

Collapse
 
greathector7 profile image
Hector Gonzalez

I have problems with some selects that are dependent, they have a lot of information and I have cleaned them before loading them to fill them out by ajax. but when sending them it gives an error of the values ​​saying that they are not valid

controlc.com/24a2fecc

Collapse
 
cswinslow profile image
Chris Winslow

"If you have more than one form in your page you can separate them by using action, so your view will not get multiple requests at the same time."

Any chance we can get an example of this? Like: how does the view.py code change to accommodate this, and how does the .js also change? I've experimented a bit, but I'm kind of lost.

Collapse
 
enesislam profile image
enesstr • Edited

what about "data-name" attr? You can assigment an attribute that starts with "data-" to separate forms in ajax section.
For instance:

//html

li data-animal-type="fish">Salmon>/li>

//js
"""
data: {'content_id': $(this).attr('data-animal-type'),
'operation':'add_new_animal',
//We will got "fish" value.

"""

w3schools.com/tags/att_data-.asp

Collapse
 
malikdeveloper2077 profile image
Malik

Bruh.. You forgot to write e.preventDefault() in ajax request

Collapse
 
celikyuksell profile image
Yuksel Celik

Thank you. I tried more 20 samples but just this work for me..

Collapse
 
nuh profile image
nūh ben

nice but where is the validation? you are not validating the inputs on the server side i think getting data from the post request and then using them directly in the model is extremely dangerous

Collapse
 
akramnarejo profile image
Akram Narejo

other than post method where do you display the posts in template that you are rendering.