Datatables Editor Create returns "POST http://127.0.0.1:8000/dashboard 400 (Bad Request)"
Datatables Editor Create returns "POST http://127.0.0.1:8000/dashboard 400 (Bad Request)"
Hello, I am trying to integrate DataTables Editor with Django and a Django REST framework API. I have created the API and am able to post data. However, when I connect it with a datatables and try to click create, I am returned an error 400 Bad Request. Would love to get some feedback if I am missing something within the Editor. Additionally if anyone knows resources where others have been able to connect Django with Datatables Editor, please connect me with them.
{% extends 'base_datatables_editor.html' %}
{% block content %}
<h1 style="text-align: center; padding-top: 1em; padding-bottom: 1em;">Investigators</h1>
<div class="row">
<div class="col-sm-12">
<table id="InvestigatorDataTable" class="table table-striped table-bordered" style="width:100%">
<thead>
<tr>
<th scope="col">First Name</th>
<th scope="col">Last Name</th>
<th scope="col">Name</th>
<th scope="col">Email</th>
<th scope="col">Institution</th>
</tr>
</thead>
</table>
</div>
</div>
{% endblock content %}
{% block extra_js %}
<script>
var editor;
var DateTime = moment().format();
function getCookie(name) {
var cookieValue = null;
if (document.cookie && document.cookie != '') {
var cookies = document.cookie.split(';');
for (var i = 0; i < cookies.length; i++) {
var cookie = jQuery.trim(cookies[i]);
// 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;
}
$(document).ready(function() {
function csrfSafeMethod(method) {
// these HTTP methods do not require CSRF protection
return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
}
$.ajaxSetup({
beforeSend: function (xhr, settings) {
if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
xhr.setRequestHeader("X-CSRFToken", csrftoken);
}
}
});
var csrftoken = getCookie('csrftoken');
editor = new $.fn.dataTable.Editor( {
ajax: {
create: {
type: "POST",
url: 'http://127.0.0.1:8000/dashboard/api/investigator/'
},
///edit: {
///type: "PUT",
///url: "http://127.0.0.1:8000/dashboard/api/investigator/_id_"
///},
///remove: {
///type: "DELETE",
///url: "http://127.0.0.1:8000/dashboard/api/investigator/_id_"
},
data: "symbol",
defaultContent: "",
contentType: 'application/json',
csrfmiddlewaretoken: window.CSRF_TOKEN,
table: '#InvestigatorDataTable',
idSrc: "id",
dataSrc: "data",
fields: [ {
label: "ID:",
name: "id"
}, {
label: "Last Name:",
name: "last_name"
}, {
label: "First Name:",
name: "first_name"
}, {
label: "Email:",
name: "email"
}, {
label: "Institution:",
name: "institution.id",
///type: "select",
///placeholder: "Select an institution"
}, {
label: "Created At:",
name: "created_at",
}]
});
$('#InvestigatorDataTable').DataTable({
serverSide: true,
ajax: {
url: "http://127.0.0.1:8000/dashboard/api/investigator/?format=datatables",
type: 'GET',
},
dom: 'Bfrtrip',
columns: [
{data: "last_name", },
{data: "first_name",},
{data: null, render: function ( data, type, row ) {
return data.first_name + " " + data.last_name
}},
{data: "email", orderable: false},
{data: "institution", name: "institution", orderable: true},
],
columnDefs: [
{ targets: [2, 3, 4,], visible: true},
{ targets: '_all', visible: false }
],
select: true,
buttons: [
{ extend: "create", editor: editor },
{ extend: "edit", editor: editor },
{ extend: "remove", editor: editor }
]
});
});
</script>
{% endblock %}
The XHR response for the POST request seems to have all the necessary fields yet it still rejects it.
Answers
You will need to look at your Django server logs to determine why its responding with the 400 Bad Request error.
I've not sued this but here is a djangorestframework-datatables-editor framework.
Kevin
Thank you however the linked project no longer works. Surprisingly, it runs into the same error where the editor create button shows 400 Bad Request.
I did have one thought, currently when the data is being sent, the JSON data looks like this. (I removed both the "id" and "created_at" field because API has an html form that accepts data without these fields)
How can I edit the data to look like this?
Maybe this thread with a similar question will help.
Did you look at the Django server logs to see why its returning a 400 error?
Maybe with the
djangorestframework-datatables-editor
library you need to send the data from the client not using JSON. I haven't used that library so not sure how well it works. Looks like its been a couple years since its been updated.The docs show what the Create data looks like. Which looks to be the same as the JSON structure being sent. I think the
preSubmit
might be the place to modify the data sent.Kevin
I looked at the Django Error Log and they only thing it has is
After expanding the logs to include more info.
Fomat: {levelname} {name} {filename} {funcName} {processName} {module} {lineno:d} {message}
(For reference on logging definitions - https://docs.python.org/3/library/logging.html#logrecord-attributes)
I'll look into sending the data not using JSON/changing how the JSON structure and post a comment with what I learn.
If it were me I would dig deeper into why the 400 is returned. Looking at this page it seems to indicate that the reason might be noted in the response. Use the browser's network inspector tool to see the response.
Using google it seems not setting the ALLOWED_HOSTS is a common issue with Django responding with 400 error. For example:
https://blog.anvileight.com/posts/how-to-fix-bad-request-400-in-django/
This SO thread indicates setting the
DEBUG
flag to True will allow seeing the error.I meant for this change if you are using the
djangorestframework-datatables-editor
framework. I don't see anything in their example where they are telling the Editor to send JSON data. It may support either, I'm not sure.Kevin
Thank you very much for all the help. Looking at the browser's network inspector has given me more information. For some reason none of the data from the fields is being entered prior to submitting.
Take a look at the Payload tab to see how the fields are sent. The errors suggest that your Django route is not parsing the create data that is being sent. Possibly you will want to send the data in JSON format. The last example in the
ajax.data
shows how to do this.Also you will need to get the fields from the
0
key as shown in the Editor Client/Server exchange for create docs. Does the payload tab show the correct data, as per the docs, being sent to the server?As I suggested above you might be able to use the
preSubmit
event to modify the data sent for thecreate
action to go fromto
I haven't used Django enough to tell you exactly how to do this. The Datatables developer is not familiar with Django. If you don't want to use thedjangorestframework-datatables-editor library maybe you can look at the source code to see how it parses the data. Or maybe there is another framework that will work for you.
Kevin
Looks like the payload tab has the same data structure from the initial JSON format that I'm trying to change.
I have also added in the preSubmit option into my editor file and it is still not working. Perhaps I created it wrong?
It looks like you are using
preSubmit
incorrectly. You don't want to return anything. It uses the return value to determine if the form should be submitted, ie, a boolean value.Look at the example in the docs and you will see it is simply updating the
data
parameter. You will probably want something like this (I haven't tested this):The Edit and Delete processes use the same structure with the key being the row ID. Is your server script setup to parse this data?
Kevin
Thanks for all the help. After thoroughly going through the linked example app, turns out I was using the wrong API url. The proper URL should be
http://127.0.0.1:8000/dashboard/api/investigator/editor/?format=datatables
rather thanhttp://127.0.0.1:8000/dashboard/api/investigator/
. This is why it kept returning ERROR 400 because it was not being properly read.Great to hear you got to the bottom of it. Thanks for letting us know.
Allan