Daniel Johnson
Daniel Johnson

Reputation: 251

Adding {% csrf_token %} to javascript HTML insertion

All,

I have a popup that is inserted via javascript when a button is clicked:

function loadTypeManagement(existingDocTypes) {
const typeManagementModalDiv =
    '<div class="modal fade" id="typeManagementModalDiv" >' +
    '<div class="modal-dialog" style="max-width: none;">' +
    '<div class="modal-content feedback_popup" style="height:100%; margin-top: 0vh;">' +
    '<form class="feedback_form" autocomplete="off" action="/" method="post" id="taskitem_form">' +

    '<h1 id="djangoInsert">Type Management</h1><br>' +
    '<hr>' +
    '<div class="autocomplete container justify-content-center">' +
    '<h3 style="margin-bottom: .5vw;">Add a Document Type</h3>' +
    '<hr style="width: 50% ;margin: auto; margin-bottom: .5vh;">' +
    '<div class="row">' +
    '<div class="col-3"></div>' +
    '<label class="col-6 admin_input_desc ">Document Type:</label>' +
    '<div class="col-3"></div>' +
    '</div>' +
    '<div class="row">' +
    '<div class="col-3"></div>' +
    '<input class=" text-center col-6 admin_input " id="addDoctypeId" type="text" name="addDocTypeName" placeholder="Document Type">' +
    '<div class="col-3"></div>' +
    '<div class="d-inline p-2 text-white ">' +
    '<p class="col-sm-4 admin_input_desc d-inline">Can this new type be an Authentication Source?</p>' +
    '<label class="">No</label>' +
    ' <input  type="radio" id="date_newToOld" name="choice" value="date_newToOld" checked/>' +
    '<label class="float-right " style="margin-left: 1.25vw;">Yes</label>' +
    ' <input  class="float-left" type="radio" id="date_newToOld" name="choice" value="date_newToOld" />' +
    '</div>' +
    '</div>' +
    '<input class="submit_button" name="submit" type="submit" value="Add Document Type">' +
    '</div>' +
    '</form>' +
    '<form class="feedback_form" autocomplete="on" action="/action_page.php">' +
    '<hr>' +
    '<div class="autocomplete container justify-content-center">' +
    '<h3 style="margin-bottom: .5vw;">Remove a Document Type</h3>' +
    '<hr style="width: 50% ;margin: auto; margin-bottom: .5vh;">' +
    '<div class="row">' +
    '<div class="col-3"></div>' +
    '<label class="col-6 admin_input_desc ">Document Type:</label>' +
    '<div class="col-3"></div>' +
    '</div>' +
    '<div class="row">' +
    '<div class="col-3"></div>' +
    '<tr>' +
    '<td  class=" text-center col-6 remove_doc_dropdown ">' +
    '<select  class=" text-center remove_doc_dropdown2 " id="m" >' +
    '<option id="-1" value="" selected disabled>Document Type</option>' +
    '</select>' +
    '</td>' +
    '</tr>' +
    '<div class="col-3"></div>' +
    '<div class="d-inline p-2 text-white ">' +
    '</div>' +
    '</div>' +
    '<input class="submit_button" type="submit" value="Remove Document Type">' +
    '</div>' +
    '<hr>' +
    '</form>' +
    '<form class="feedback_form" autocomplete="on" action="/action_page.php">' +
    '<div class="autocomplete container justify-content-center">' +
    '<h3 style="margin-bottom: .5vw;">Change a Document Type</h3>' +
    '<hr style="width: 50% ;margin: auto; margin-bottom: .5vh;">' +
    '<div class="row">' +
    '<div class="col-3"></div>' +
    '<label class="col-6 admin_input_desc ">Change Document Type:</label>' +
    '<div class="col-3"></div>' +
    '</div>' +
    '<div class="row">' +
    '<div class="col-3"></div>' +
    '<tr>' +
    '<td  class=" text-center col-6 remove_doc_dropdown ">' +
    '<select  class=" text-center remove_doc_dropdown2 " id="m2" >' +
    '<option id="-1" value="" selected disabled>Document Type</option>' +
    '</select>' +
    '</td>' +
    '</tr>' +
    '<div class="col-3"></div>' +
    '</div>' +
    '<div class="row">' +
    '<div class="col-3"></div>' +
    '<label class="col-6 admin_input_desc ">To Document Type:</label>' +
    '<div class="col-3"></div>' +
    '</div>' +
    '<div class="row">' +
    '<div class="col-3"></div>' +
    '<input class=" text-center col-6 admin_input " id="myInput" type="text" name="myCountry" placeholder="Document Type">' +
    '<div class="col-3"></div>' +
    '<div class="d-inline p-2 text-white ">' +
    '</div>' +
    '</div>' +
    '<div class="row">' +
    '<div class="col-4"></div>' +
    '<input class="col-4 submit_button" type="submit" value="Change Document Type">' +
    '<div class="col-4"></div>' +
    '<div class="d-inline p-2 text-white ">' +
    '</div>' +
    '</div>' +
    '<hr>' +
    '</form>' +
    '</div>' +
    '</div>' +
    '</div>';
const newDiv = document.createElement("div");
newDiv.innerHTML = typeManagementModalDiv;
var data = $('form').serialize()
document.body.appendChild(newDiv);

for (i = 0; i < existingDocTypes.length; i++) {
    var opt = document.createElement("option");
    document.getElementById("m").innerHTML += '<option class="option_value" value = "' + existingDocTypes[i] + '" id="' + i + '">' + existingDocTypes[i] + '</option>';
    document.getElementById("m2").innerHTML += '<option class="option_value" value = "' + existingDocTypes[i] + '" id="' + i + '">' + existingDocTypes[i] + '</option>';
}

I am trying to submit the form and keep getting the error "CSRF token missing or incorrect." I've tried to insert it via string '{% csrf_token %}', but that just leaves the string value and Django doesn't pick up on it.

Any idea how I can do this? Is there a better way?

Upvotes: 0

Views: 826

Answers (1)

Daniel Johnson
Daniel Johnson

Reputation: 251

I'm not completely sure if there are any security concerns using this method (please let me know if there are), but I was able to initiate the {{ csrftoken }} within the template using:

<script>
    var csrftoken = '{{ csrf_token }}';
</script>

and then passing that token value to the JS function like so:

        <a onclick="loadTypeManagement({{ existingDocTypes }}, csrftoken);" id="feedbackButton" data-toggle="modal" data-target="#typeManagementModalDiv" class="hide_table_button underline_none" href="{% url 'admin:login' %}">Type Management</a>

Then, within the JS, I was able to add the line:

'<input type="hidden" name="csrfmiddlewaretoken" value="' + csrftoken + '">' +

which holds the token value.

So, the full JS looks like this:

function loadTypeManagement(existingDocTypes, csrftoken) {
    console.log(csrftoken)
    const typeManagementModalDiv =
        '<div class="modal fade" id="typeManagementModalDiv" >' +
        '<div class="modal-dialog" style="max-width: none;">' +
        '<div class="modal-content feedback_popup" style="height:100%; margin-top: 0vh;">' +
        '<form class="feedback_form" autocomplete="off" action="/adminFunct/" method="post" id="taskitem_form">' +
        '<input type="hidden" name="csrfmiddlewaretoken" value="' + csrftoken + '">' +
        '<h1 id="djangoInsert">Type Management</h1><br>' +
        '<hr>' +
        '<div class="autocomplete container justify-content-center">' +
        '<h3 style="margin-bottom: .5vw;">Add a Document Type</h3>' +
        '<hr style="width: 50% ;margin: auto; margin-bottom: .5vh;">' +
        '<div class="row">' +
        '<div class="col-3"></div>' +
        '<label class="col-6 admin_input_desc ">Document Type:</label>' +
        '<div class="col-3"></div>' +
        '</div>' +
        '<div class="row">' +
        '<div class="col-3"></div>' +
        '<input class=" text-center col-6 admin_input " id="addDoctypeId" type="text" name="addDocTypeName" placeholder="Document Type">' +
        '<div class="col-3"></div>' +
        '<div class="d-inline p-2 text-white ">' +
        '<p class="col-sm-4 admin_input_desc d-inline">Can this new type be an Authentication Source?</p>' +
        '<label class="">No</label>' +
        ' <input  type="radio" id="date_newToOld" name="choice" value="date_newToOld" checked/>' +
        '<label class="float-right " style="margin-left: 1.25vw;">Yes</label>' +
        ' <input  class="float-left" type="radio" id="date_newToOld" name="choice" value="date_newToOld" />' +
        '</div>' +
        '</div>' +
        '<input class="submit_button" name="submit" type="submit" value="Add Document Type">' +
        '</div>' +
        '</form>' +
        '<form class="feedback_form" autocomplete="on" action="/action_page.php">' +
        '<hr>' +
        '<div class="autocomplete container justify-content-center">' +
        '<h3 style="margin-bottom: .5vw;">Remove a Document Type</h3>' +
        '<hr style="width: 50% ;margin: auto; margin-bottom: .5vh;">' +
        '<div class="row">' +
        '<div class="col-3"></div>' +
        '<label class="col-6 admin_input_desc ">Document Type:</label>' +
        '<div class="col-3"></div>' +
        '</div>' +
        '<div class="row">' +
        '<div class="col-3"></div>' +
        '<tr>' +
        '<td  class=" text-center col-6 remove_doc_dropdown ">' +
        '<select  class=" text-center remove_doc_dropdown2 " id="m" >' +
        '<option id="-1" value="" selected disabled>Document Type</option>' +
        '</select>' +
        '</td>' +
        '</tr>' +
        '<div class="col-3"></div>' +
        '<div class="d-inline p-2 text-white ">' +
        '</div>' +
        '</div>' +
        '<input class="submit_button" type="submit" value="Remove Document Type">' +
        '</div>' +
        '<hr>' +
        '</form>' +
        '<form class="feedback_form" autocomplete="on" action="/action_page.php">' +
        '<div class="autocomplete container justify-content-center">' +
        '<h3 style="margin-bottom: .5vw;">Change a Document Type</h3>' +
        '<hr style="width: 50% ;margin: auto; margin-bottom: .5vh;">' +
        '<div class="row">' +
        '<div class="col-3"></div>' +
        '<label class="col-6 admin_input_desc ">Change Document Type:</label>' +
        '<div class="col-3"></div>' +
        '</div>' +
        '<div class="row">' +
        '<div class="col-3"></div>' +
        '<tr>' +
        '<td  class=" text-center col-6 remove_doc_dropdown ">' +
        '<select  class=" text-center remove_doc_dropdown2 " id="m2" >' +
        '<option id="-1" value="" selected disabled>Document Type</option>' +
        '</select>' +
        '</td>' +
        '</tr>' +
        '<div class="col-3"></div>' +
        '</div>' +
        '<div class="row">' +
        '<div class="col-3"></div>' +
        '<label class="col-6 admin_input_desc ">To Document Type:</label>' +
        '<div class="col-3"></div>' +
        '</div>' +
        '<div class="row">' +
        '<div class="col-3"></div>' +
        '<input class=" text-center col-6 admin_input " id="myInput" type="text" name="myCountry" placeholder="Document Type">' +
        '<div class="col-3"></div>' +
        '<div class="d-inline p-2 text-white ">' +
        '</div>' +
        '</div>' +
        '<div class="row">' +
        '<div class="col-4"></div>' +
        '<input class="col-4 submit_button" type="submit" value="Change Document Type">' +
        '<div class="col-4"></div>' +
        '<div class="d-inline p-2 text-white ">' +
        '</div>' +
        '</div>' +
        '<hr>' +
        '</form>' +
        '</div>' +
        '</div>' +
        '</div>';
    const newDiv = document.createElement("div");
    newDiv.innerHTML = typeManagementModalDiv;
    document.body.appendChild(newDiv);
    for (i = 0; i < existingDocTypes.length; i++) {
        var opt = document.createElement("option");
        document.getElementById("m").innerHTML += '<option class="option_value" value = "' + existingDocTypes[i] + '" id="' + i + '">' + existingDocTypes[i] + '</option>';
        document.getElementById("m2").innerHTML += '<option class="option_value" value = "' + existingDocTypes[i] + '" id="' + i + '">' + existingDocTypes[i] + '</option>';
    }

For any curious, this portion is used for dropdown stuff and not needed for anything related to the csrf_token

 for (i = 0; i < existingDocTypes.length; i++) {
        var opt = document.createElement("option");
        document.getElementById("m").innerHTML += '<option class="option_value" value = "' + existingDocTypes[i] + '" id="' + i + '">' + existingDocTypes[i] + '</option>';
        document.getElementById("m2").innerHTML += '<option class="option_value" value = "' + existingDocTypes[i] + '" id="' + i + '">' + existingDocTypes[i] + '</option>';
    }

Upvotes: 1

Related Questions