Home Blog CV Projects Patterns Notes Book Colophon Search

AJAX with Django CSRF

4 Feb, 2018

Here's the AJAX code I use with CSRF protection to post a Django form in HTML:

// Based loosely on https://www.quirksmode.org/js/xmlhttp.html and https://docs.djangoproject.com/en/3.1/ref/csrf/#ajax
function sendRequest(url,callback,errback,postData,csrftoken) {
    var req = createXMLHTTPObject();
    if (!req) return;
    var method = (postData) ? "POST" : "GET";
    req.open(method,url,true);
    req.setRequestHeader('X-CSRFToken', csrftoken);
    if (postData)
        req.setRequestHeader('Content-type','application/json');
    req.onreadystatechange = function () {
        if (req.readyState != 4) return;
        if (req.status != 200 && req.status != 201 && req.status != 304) {
            console.log('HTTP error ' + req.status);
            errback(req);
            return;
        }
        callback(req);
    }
    if (req.readyState == 4) return;
    req.send(postData);
}

var XMLHttpFactories = [
    function () {return new XMLHttpRequest()},
    function () {return new ActiveXObject("Msxml2.XMLHTTP")},
    function () {return new ActiveXObject("Msxml3.XMLHTTP")},
    function () {return new ActiveXObject("Microsoft.XMLHTTP")}
];

function createXMLHTTPObject() {
    var xmlhttp = false;
    for (var i=0;i<XMLHttpFactories.length;i++) {
        try {
            xmlhttp = XMLHttpFactories[i]();
        }
        catch (e) {
            continue;
        }
        break;
    }
    return xmlhttp;
}

var callback = function(req) {
    var r = req.response;
    var data = JSON.parse(r);
    console.log(data);
    var author = document.createElement("span");
    author.classList.add("author");
    author.appendChild(document.createTextNode(data.author));
    var posted = document.createElement("span");
    posted.classList.add("posted");
    var d = new Date();
    posted.appendChild(document.createTextNode(data.posted));
    var comment = document.createElement("span");
    comment.classList.add("comment");
    comment.appendChild(document.createTextNode(data.comment));
    var div = document.createElement("div");
    div.classList.add("comment");
    div.appendChild(author);
    div.appendChild(document.createTextNode(' - '));
    div.appendChild(posted);
    var br = document.createElement("br");
    div.appendChild(br);
    div.appendChild(comment);
    var element = document.getElementById("new_comments");
    element.appendChild(div);
    alert('Comment addedd successfully');
    document.forms[0].elements['author'].value = '';
    document.forms[0].elements['comment'].value = '';
}

var errback = function(req) {
    alert('Sorry, there was a problem adding the comment')
}

function getCookie(name) {
    var cookieValue = null;
    if (document.cookie && document.cookie !== '') {
        const cookies = document.cookie.split(';');
        for (var i = 0; i < cookies.length; i++) {
            const cookie = cookies[i].trim();
            // Does this cookie string begin with the name we want?
            if (cookie.substring(0, name.length + 1) === (name + '=')) {
                cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
                break;
            }
        }
    }
    return cookieValue;
}


const csrftoken = getCookie('csrftoken');
document.forms[0].onsubmit = function(e){
    console.log(e);
    e.preventDefault();
    var parts = location.href.split('/')
    var data = JSON.stringify({
        "author": e.target.elements['author'].value,
        "comment": e.target.elements['comment'].value,
        "webpage": location.pathname.slice(1, location.pathname.length - parts[parts.length-1].length - 1)
    });
    sendRequest(
        '/api/comments/',
        callback,
        errback,
        data,
        csrftoken
    );
    return false;
}

Comments

Be the first to comment.

Add Comment





Copyright James Gardner 1996-2020 All Rights Reserved. Admin.