0

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']
                }>
  1. Why is this happening?
  2. Why is 'flag' not behaving the same way? (I outright hard-code flag as a "string" in my JS)
  3. 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();
Mormoran
  • 751
  • 13
  • 34
  • In Django you can use [`get()`](https://docs.djangoproject.com/en/2.0/ref/request-response/#django.http.QueryDict.getlist) or [`getList`](https://docs.djangoproject.com/en/2.0/ref/request-response/#django.http.QueryDict.getlist) depending on whether you want a single item or a list of items. Django doesn't do anything special with `[]` in key names, you can turn off that feature of jQuery using the traditional setting. – Alasdair Apr 11 '18 at 11:07
  • So it's basically safe to set traditional to true in Django use cases? Is it possible to use settings on $.post functions? I have plenty of them and if I can avoid changing them all to $.ajax I'd prefer that – Mormoran Apr 11 '18 at 11:12
  • Yes, you should be able to use it with `$.post`. – Alasdair Apr 11 '18 at 12:00
  • Would you know where in my $.post I declare settings? I can't seem to get it to work. – Mormoran Apr 11 '18 at 12:24
  • It looks as if you need to use the [second form](https://api.jquery.com/jquery.post/#jQuery-post-settings), e.g. `$.post({url: url, data: {...}, traditional: true})`. If you are only doing ajax requests to the Django API, then using `$.ajaxSetup` seems like a good option. – Alasdair Apr 11 '18 at 12:52
  • Brilliant, that was the mistake. If you post that as an answer I will accept it. – Mormoran Apr 11 '18 at 13:09
  • Your question still has lots of stuff which is covered by the duplicate question. If you simplify it down to "how do I use `traditional: true` with `$.post` then I'll re-open it and add the answer. – Alasdair Apr 11 '18 at 13:17
  • It is always better to look straight into the [docs](https://api.jquery.com/jquery.post/#jQuery-post-url-data-success-dataType) before trying different combinations, saves time. And [googling](https://www.google.com/search?q=jquery+encodes+array+with+square+brackets) brings up the [perfect question with perfect answers](https://stackoverflow.com/questions/2540827/jquery-parameter-serialization-without-the-bracket-mess/2540897) twice in the result. – Munim Munna Apr 11 '18 at 20:58

0 Answers0