Sending POST data to a Django view via AJAX to a REST endpoint

Use JavaScript's fetch to connect to a Django REST API URL

If you want to send some POST data to an endpoint URL using AJAX, say for example, adding employee data to the database via a popup and not via the regular <form> method, we need to extract the csrf_token value from the generated input tag.

Template (for eg. add-employee.html) :

{% csrf_token %}

We need to extract the value of the input element that Django generates like this in HTML :

<input type="hidden" name="csrfmiddlewaretoken" value="ktzIX6zdGAhusuPOK5bSHbzfabByXi0q8wu7YfkTX46vFvA5IQvrb9GXUZVqJVEx">

We'll use JavaScript to extract it :

const csrftoken = document.querySelector('[name=csrfmiddlewaretoken]').value;

These are documented here in Django 4.2 and here in Django 4.0.

When sending the data in JavaScript via fetch or using a library like axios, you need to send in the 'X-CSRFToken' header with the csrftoken value (which we extracted just now above)

This becomes the JavaScript code which you can temporarily place in the add-employee.html file itself for now wrapped in a <script> tag.

const BASE_URL = '{{ request.scheme }}://{{ request.get_host }}/';
const csrftoken = document.querySelector('[name=csrfmiddlewaretoken]').value;
let global_data = { name: "John", age: 31, code: "IN414" };

let submitFormData = () =>
{
    const API_URL = BASE_URL + "/api/employee/add";

    const request = new Request(
        API_URL,
        { headers: { 'X-CSRFToken': csrftoken } }
    );

    return fetch(request, {
            method: 'POST',
            mode: 'same-origin',
            body: JSON.stringify(global_data) })
    .then(response => response.json())
    .then(response =>
        {
            data = response['time']; return data;
        });
}

Now in the urls.py file add :

path('api/add', views.api_add, name='api_add'),

And in the views.py file :

from django.shortcuts import render, HttpResponse
import json

def api_add(request):

    t1 = datetime.datetime.now()

    print(request.body)

    if request.method == 'POST':
        data = json.loads(request.body)
        print(data)
        json_obj = json.dumps({ "time": str(datetime.datetime.now() - t1), "method": "post" })
    else:
        print("Only POST allowed")
        json_obj = json.dumps({ "time": str(datetime.datetime.now() - t1), "method": "get" })


    result = HttpResponse(json_obj, 'application/json', charset='utf-8')

    return result

Now if you run python manage.py runserver and click on the submit button, you should be able to see a POST XHR request being made in the console of FireFox (Network in Chrome).

POST localhost:8000/api/employee/add