The duplicate answer explains how to solve this using $.ajax. I'm using $.post, though I don't understand how to set settings individually for $.post use cases, which I've used 20+ times throughout the project. Yet the documentation hints this is possible and one comment on this thread states that it is.
I'm trying to do a post request to my Django view using jQuery's $.post.
The elements I'm trying to get to Python are lists (arrays) that I build off of multiple IDs.
Here is my jQuery code:
var newBaseline = function () {
// Initialize arrays each time the function is run
var timeArray = [];
var parametersArray = [];
var runsArray = [];
// Cycle through some input elements and get their values, push to array
timeRangeInputs.each(function() {
timeArray.push($(this).val());
});
// Cycle through some checkboxes and get their data-id values, push to array
parameterContainer.find("input:checked").each(function() {
parametersArray.push($(this).data("parameter_id"));
});
// Cycle through some checkboxes and get their data-id values, push to array
runContainer.find("input:checked").each(function() {
runsArray.push($(this).data("run_id"));
});
// Just a flag for my view so I can do if-else cases in python
// as the view handles several forms in the same page
var flag = "new-baseline";
$.post("{% url 'my_view %}", {
csrfmiddlewaretoken: "{{csrf_token}}",
timeArray: timeArray,
parametersArray: parametersArray,
runsArray: runsArray,
flag: flag
}, function(data) {
// check valid or errors, etc
}).done();
};
The problem arises when I go to my Python view. The request.POST QueryDict object comes in fine, but the arrays have additional []'s appended.
print(request.POST)
>>> <QueryDict: {'runsArray[]': ['3, 7'],
'csrfmiddlewaretoken': ['foobar'],
'parametersArray[]': ['409'],
'timeArray': ['257.5674', '591.8532'],
'flag': ['new-baseline']
}>
- Why is this happening?
- Why is 'flag' not behaving the same way? (I outright hard-code flag as a "string" in my JS)
- Why is the hardcoded string value of 'flag' turned into a list of strings? ['new-baseline']
It seems strange that in order to get the list values in python I have to add an extra[] to my keys that was never included in my JS:
print(request.POST.getlist('runsArray[]')
>>> ['3, 7']
rather than:
print(request.POST.getlist('runsArray')
>>> None
This may stem from a lack of understanding how a jQuery $.post is done, what happens internally and/or how Django (or even Python) handles a request method, but instead of just adding an extra "[]", I'd like to understand why this is happening, if it's normal or if I'm doing something wrong.
[EDIT]
Trying to get settings working with $.post, rather than having to change to $.ajax.
As far as I understand from reading the documentation, adding setttings to $.post is possible, yet it doesn't show an example. It does for $.ajax, but it's not clear if I'm assumed to have to change $.post to $.ajax if I want to use settings.
Tried:
$.post(
"{% url 'my_django_url' %}",
{
csrfmiddlewaretoken: "{{csrf_token}}",
timeArray: timeArray,
parametersArray: parametersArray,
runsArray: runsArray,
flag: flag
},
traditional: true
)
Or:
$.post(
"{% url 'my_django_url' %}",
{
csrfmiddlewaretoken: "{{csrf_token}}",
timeArray: timeArray,
parametersArray: parametersArray,
runsArray: runsArray,
flag: flag,
traditional: true
})
Or:
$.post(
"{% url 'my_django_url' %}",
{
csrfmiddlewaretoken: "{{csrf_token}}",
timeArray: timeArray,
parametersArray: parametersArray,
runsArray: runsArray,
flag: flag
},
settings={traditional: true})
Or:
$.post(
"{% url 'my_django_url' %}",
{
csrfmiddlewaretoken: "{{csrf_token}}",
timeArray: timeArray,
parametersArray: parametersArray,
runsArray: runsArray,
flag: flag
},
{traditional: true})
Neither work, yet the documentation states that settings is a set of key: value pairs. It doesn't really specify or show how or where to use them.
The linked "duplicate" explains how to solve for $.ajax but that was not the question being asked.
The extra brackets disappear if I just add
$.ajaxSetup({
traditional: true
});
But that would set that to default for all ajax calls. I'm not sure whether that is a good idea or if it will negatively affect future uses of the method (or even one of the other 20+ uses through the project).
[SOLUTION]
Just in case someone else runs into this in the future:
The problem was in not declaring key: value pairs for all arguments in the method call. It makes sense now, but I didn't see it before. Instead of just passing the parameters as default, you have to specify which one is url, data, success (optional) and settings (as straight key: value pairs, without declaring a "settings" dict or list).
IE:
$.post({
url: "{% url 'my_django_url' %}",
data: {
csrfmiddlewaretoken: "{{csrf_token}}",
timeArray: timeArray,
parametersArray: parametersArray,
runsArray: runsArray,
flag: flag
},
success: function(data) {
console.log("Success! ");
console.log(data);
},
traditional: true
}).done();