jayt
jayt

Reputation: 768

Django - Posting jQuery dictionary via Ajax prints None in views.py

I have an Ajax function in my Django project resembling the following...

$('#btn-submit').click(function(e){
  e.preventDefault();
  var btn = $(this);
  var dataUrl = btn.attr('data-href');
  var title = $('#title').val();
  var dict = {};
  $('.choice-m2m-check').each(function(i){
    k = $(this).val();
    v = $(this).attr('data-value');
    dict[k] = v;
  });
  $.ajax({
    url:dataUrl,
    method:'POST',
    data:{
      'title':title,
      'dict':dict,
    },
    success:function(data){
      if (data.saved){
        ...
      }
    },
    error:function(error){
      ...
    }
  });
});

So I have a {key: value, ...} dictionary which assigns a 'true' or 'false' boolean flag to each item. This is then posted to the URL represented by 'dataUrl' where Python does some checks on the data.

So firstly, in the jQuery after the key value pairs have been assigned, I console log the value of dict using console.log(dict) which gives me something like the following {item-885564895: "true", item-0385245877: "false"} in the console.

The problem is that in my Django view where I print the posted value of request.POST.get('dict') then it prints None. Note that when I print the 'title' field which is a regular string then printing it returns the value of the title. What am I doing wrong?

Upvotes: 3

Views: 1306

Answers (2)

vinay
vinay

Reputation: 1416

Error seems to be on js side. It looks like the title field have same id and name i.e. title. So when the button is clicked, the form got submitted directly without calling this function. Better try adding logs in this function. If the button is added dynamically, then try using below

$('#btn-submit').on('click',function(e){
  e.preventDefault();
  alert("This function called")  
});

Upvotes: 0

willeM_ Van Onsem
willeM_ Van Onsem

Reputation: 477318

As far as I know you can not send a JavaScript object as payload in a HTTP request. After all JavaScript constists out of more than only dictionaries, integers, strings, etc. How would you for example transfer a function to the server? How is the server supposed to handle that?

What you thus need is some sort of format: a way to encode the data to a type that can be used as payload: a string. Now standard JavaScript objects have a popular format: the JavaScript Object Notation, or in short JSON.

We can thus encode the dict entry to a JSON string with JSON.stringify(..):

$('#btn-submit').click(function(e){
  e.preventDefault();
  var btn = $(this);
  var dataUrl = btn.attr('data-href');
  var title = $('#title').val();
  var dict = {};
  $('.choice-m2m-check').each(function(i){
    k = $(this).val();
    v = $(this).attr('data-value');
    dict[k] = v;
  });
  $.ajax({
    url:dataUrl,
    method:'POST',
    data:{
      'title': title,
      'dict': JSON.stringify(dict),
    },
    success:function(data){
      if (data.saved){
        ...
      }
    },
    error:function(error){
      ...
    }
  });
});

Now of course the Django backend will not automatically transfer this into Python objects: it sees a string and hence handles it as a string. But JSON can be decoded in vanilla Pyhon objects (a dict, bool, etc.) with json.loads:

from json import loads as jsonloads

def my_view(request):
    mydict = jsonloads(request.POST.get('dict'))
    # process mydict
    # ...
    pass

Upvotes: 5

Related Questions