0

I'm a backend developer who is learning to become a fullstack. In my issue I am using jQuery on frontend and Python/Django 3.2 on the backend.

I'm having a major problem sending a nested object through with $.ajax. Here is the code:

$("#idForm").submit(function (event) {
  var formData = {
      name: $("#name").val(),
      value: $("#value").val(),
      is_default: $("#default").val(),
      data_origin: {
          manual: [],
          literature: [],
          external: [],
          software: []
      }
  };
  let selected = $("input[name=data_origin_type]:checked").val();
  if(selected == "manual"){
      let obj = {};
      obj.comment = $("#id_data_origin_manual_comment").val();
      formData.data_origin.manual.push(obj);
  } else if (selected == "literature") {
      formData.data_origin.literature.push(
          {
              title: $("#id_data_origin_literature_title").val(),
              authors: $("#id_data_origin_literature_authors").val(),
              year: $("#id_data_origin_literature_year").val(),
              link: $("#id_data_origin_literature_link").val(),
              journal_name: $("#id_data_origin_literature_journal_name").val(),
              page: $("#id_data_origin_literature_page").val(),
              volume_nr: $("#id_data_origin_literature_volume_nr").val()
          }
      );
  } else if (selected == "external"){
      formData.data_origin.external.push(
          {
              source_entity: $("#id_data_origin_external_source").val()
          }
      );
  } else if (selected == "software"){
      formData.data_origin.software.push(
          {
              sotware: $("#id_data_origin_sotware").val()
          }
      );
  } else {
      alert("Wrong data origin type");
  }
  console.log(formData);
  $.ajax({
      type: "POST",
      url: "/compounds/api/curate/" + getCompoundId(),
      data: formData,
      dataType: "application/json",
      headers: {
          'X-CSRFToken': getCSRFToken()
      }
  }).done(function (data) {
      console.log(data);
  });

  event.preventDefault();
  });
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.0/vue.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.0/jquery.min.js"></script>

When I submit the form using the above code, instead of sending data_origin as an object in sense:

{
  'name': 'inserted name',
  'value': 'inserted value',
  'default': 'on',
  'data_origin': {
    'manual': [{'comment': 'inserted comment'}],
    'literature': [{'title': 'the title', 'authors': 'John Doe', 'year': '1999'...}],
    'external': ['321'],
    'software': ['123']
  }
}

It sends it (in case of manual) as "data_origin[manual][0][comment]": "actual comment". In case of literature it adds:

"data_origin[literature][0][title]": "Actual title",
"data_origin[literature][0][authors]": "John J. Doe",
"data_origin[literature][0][year]": "1999",
"data_origin[literature][0][link]": "https://google.com",
"data_origin[literature][0][journal_name]": "inserted name",
"data_origin[literature][0][page]": "1",
"data_origin[literature][0][volume_nr]": "2"

Instead of the object, it adds it's... I don't know, a string representation of it? Displaying 'raw' query, it displays:name=fewa&value=fewa&is_default=on&data_origin%5Bliterature%5D%5B0%5D%5Btitle%5D=fawe&data_origin%5Bliterature%5D%5B0%5D%5Bauthors%5D=fewf&data_origin%5Bliterature%5D%5B0%5D%5Byear%5D=1987&data_origin%5Bliterature%5D%5B0%5D%5Blink%5D=https%3A%2F%2Fwww.google.com&data_origin%5Bliterature%5D%5B0%5D%5Bjournal_name%5D=fewf&data_origin%5Bliterature%5D%5B0%5D%5Bpage%5D=1&data_origin%5Bliterature%5D%5B0%5D%5Bvolume_nr%5D=2

NOTE: The console.log of the formData actually displays it properly as a nested object, the one I want to send.

And after 48h of debugging I'm losing my mind. I believe it's probably some quirk of JS or jQuery I'm not familiar with, but I don't know what it is.

Please help!

Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
Eric Luther
  • 117
  • 1
  • 10
  • 1
    `data: { data: JSON.stringify(formData) }`. You might need to deserialize `request.POST.get('data', '')` server side – Cid Jun 29 '23 at 13:03
  • It is deserialized on the server side with DRF, but it is deserialized as it is sent. The first three values are ok, but the nested thing is wrong. I could manually deserialize it, but that doesn't seem like the right way. – Eric Luther Jun 29 '23 at 14:26
  • Does this answer your question? [jQuery posting valid json in request body](https://stackoverflow.com/questions/4159701/jquery-posting-valid-json-in-request-body) – kmoser Jun 29 '23 at 16:39
  • Not really, though it's a workaround. When I do JSON.stringify(formData), now it's being sent as: "" : ['']. So I can work it around, by just decoding the key, as it is what I need, but that's not a pretty solution :-/ – Eric Luther Jun 30 '23 at 10:11

1 Answers1

0

So I solved it, and it is a prime example, you can't trust everything that's on the web. Instead of

data: formData,
dataType: "application/json",

I changed to:

data: JSON.stringify(formData),
contentType: 'application/json',

and now it works as it's supposed to.

Eric Luther
  • 117
  • 1
  • 10