I am making a very small application to learn Django. I am send a nested array from jQuery and trying to loop it in my Django view.
The jQuery code is as follows:
$(document).on('click','#exModel',function () {
const sending = [];
$("table tr").each(function () {
var p1 = $(this).find("th label").html();
var p2 = $(this).find("td input").attr('id');
var p3 = $(this).find("td input").val();
const build = [];
build.push(p1, p2, p3);
sending.push(build);
console.log(sending);
});
$.ajax({
url: '../coreqc/exModel/',
data: {'sending': sending},
type: 'post',
headers: {'X-CSRFToken': '{{ csrf_token }}'},
async: 'true',
success: function (data) {
console.log("I made it back")
//dom: 'Bfrtip',
}
});
});
The above works and takes the following form in the console: Note that the 3rd value is intentionally empty as I sent the form with no values in the fields to get the console read out.
[Log] [["Product A", "1", ""], ["Product B", "2", ""], ["Product C", "3", ""], ["Product D", "4", ""], ["Product E:", "5", ""], ["Product F", "6", ""], ["Product G", "7", ""], ["Product H", "8", ""], ["Product I", "9", ""], ["Product K", "10", ""], …] (36) (coreqc, line 491)
[Log] I made it back # This is the success text in the above jQuery code
It is making it to my view and I am able to print() the output to the shell:
exModel view:
def exModel(request):
sentData = request.POST
print(sentData)
template = loader.get_template('coreqc/tester.html')
context = {
'sentData':sentData
}
return HttpResponse(template.render(context, request))
Now, 'sentData' does print to the shell but it does not look right to me or at least the 'sending[1][]
' part does not. When I say it does not look right, I do not understand the empty square bracket. I can not access sending like sending[1][2]
- I get a dictionary key error.
<QueryDict: {'sending[0][]': ['Product A:', '1', ''], 'sending[1][]': ['Product B', '2', ''], 'sending[2][]': ['Product C', '3', ''], 'sending[3][]': ['Product D', '4', ''], 'sending[4][]': ['Product E', '5', ''], 'sending[5][]': ['Product F', '6', ''], 'sending[6][]': ['Product G', '7', ''], 'sending[7][]': ['Product I', '8', '']}>
What I would like to be able do is to loop through each of values in the QueryDict in a loop in my view, not just print them. However, I am unsure how I access them or whether what is being sent is accessible.
get.values() - works and I can print to console - looks same as above.
I can loop and print like so:
for x, obj in sentData.items():
print(x)
for y in obj:
print(y + ':', obj[y])
However I just get this output, it prints the below:
sending[0][]
sending[1][]
sending[2][]
sending[3][]
What I need is to access to the inner values i.e. "Product A", and I am not quite sure on how I do this.
So in summary:
Many thanks for any help.
Update: Following on from comments I have looked heavily into the content being sent Jquery. I found that despite changing headers etc it was coming across as url encoded. I fixed the headers and tested for content type and it is now coming across as application/json. However, the issue I have now is that the request.body is full of '%' symbols like so:
application/json
[26/Oct/2024 09:10:09] "POST /coreqc/exModel/ HTTP/1.1" 200 4631
b'sending%5B0%5D%5B%5D - this continues. I believe all the data is there but maybe it's unicode issue.
This turned out, after some pointers in another question, to be an access issue. However advice here on json.loads() and request.body() also formed part of the answer. Another additional was JSON.stringify() and that instead of nesting an array in an array, I nested an object inside an array - not sure how much difference that made but its in the end result.
The JSON being sent was valid. After adding the json.loads() and the using request.body instead of request.POST, I still needed to access the values and keys which I will share below:
JQuery:
$(document).on('click','#exModel',function () {
const sending = [];
$("table tr").each(function () {
var p1 = $(this).find("th label").html();
var p2 = $(this).find("td input").attr('id');
var p3 = $(this).find("td input").val();
const build = {bnaa:p1,id:parseInt(p2),vals:parseInt(p3)};
sending.push(build);
// build.push(p1, p2, p3);
});
console.log(sending);
//console.log(JSON.parse(JSON.stringify(sending)));
$.ajax({
url: '../coreqc/exModel/',
data: JSON.stringify({'sending':sending}),
//data: {'sending':sending},
//processData: false,
type: 'POST',
headers: {'content_type':'application/json','X-CSRFToken': '{{ csrf_token }}'},
// headers: {'X-CSRFToken': '{{ csrf_token }}'},
async: 'true',
success: function (data) {
console.log("I made it back")
//dom: 'Bfrtip',
}
});
Then in my view:
def exModel(request):
data = request.body
data = json.loads(request.body)
print(type(data))
for i in range(len(data['sending'])):
print(data['sending'][i]['bnaa'])
print(data['sending'][i]['id'])
print(data['sending'][i]['vals'])
template = loader.get_template('coreqc/tester.html')
context = {
#'blabla':blabla
}
return HttpResponse(template.render(context, request))
Note I have not dealt with the response yet but the above will give you access to individual values, which will print to your terminal.