I'm new to Backbone.js and I'm trying to save a model instance. I'm using django as my server.
Client side Code:
var Song = Backbone.Model.extend({
defaults: {
name: 'New Song'
},
url: function() {
return window.location.href;
}
});
var song = new Song()
song.save()
csrfmiddlewaretoken
is set properly before the data is sent.
I stepped through the jQuery $.ajax function called internally by Backbone.sync and found that the model object contains the correct data.
However, the request.POST
received by the server is
POST:<QueryDict: {u'[object Object]': [u'']}>
instead of the actual data. Any idea where I'm going wrong?
Update: I did a quick fix by setting Backbone.emulateJSON
to true. But according to the comments in the Backbone (0.9.2) code it is meant for legacy servers. I'm using Django 1.4.1. Does it mean django 1.4.1 is incompatible?
Update 2: When I set Backbone.emulateJSON
to false
, I get the following error in firefox but it fails silently in chrome.
"[Exception... "Component returned failure code: 0x80460001
(NS_ERROR_CANNOT_CONVERT_DATA)" nsresult: "0x80460001 (NS_ERROR_CANNOT_CONVERT_DATA)"
location: "JS frame :: http://localhost:8000/static/jquery.js :: <TOP_LEVEL> :: line 8214" data: no]"
I'm using jQuery for ajax as preferred by Backbone and it seems the error might be in jQuery.
Update 3: I solved it by overriding the $.ajax used by Backbone.sync with my own. It is still a quick fix.
Backbone.js verson: 0.9.2
jQuery version: 1.8.0. Also tried with 1.7.2. Same result.
I was having a similar issue and through some detective work/luck I figured it out. The issue is that by default Backbone sends the POST data as a JSON encoded string in the body of the request not as a part of the request.POST
QueryDict. So to get the data in this case you would have to use the python json library and call json.loads(request.body)
in the Django view to read the data properly.
As an aside, the reason that setting Backbone.emulateJSON = true;
works is because then Backbone sends the JSON to Django through the "legacy" mechanism which makes it appear in the request.POST
QueryDict.
If you want the data to be available in the QueryDict request.POST, then you will have to override the Backbone.sync method.
First of all you will have to set Backbone.emulateJSON to true.
You can have a look at the Backbone.sync method over here. You will notice that the model attributes are stringified.
if (options.data == null && model && (method === 'create' || method === 'update' || method === 'patch')) {
params.contentType = 'application/json';
params.data = JSON.stringify(options.attrs || model.toJSON(options));
}
Edit this part of the function to:
if (options.data == null && model && (method === 'create' || method === 'update' || method === 'patch')) {
params.contentType = 'application/json';
if(options.emulateJSON){
params.data = options.attrs || model.toJSON(options);
}else{
params.data = JSON.stringify(options.attrs || model.toJSON(options));
}
}
On some other line you will notice that Backbone adds a 'model' key to the POST QueryDict.
params.data = params.data ? {model: params.data} : {};
Edit this line to:
params.data = params.data ? params.data : {};
Thats it! Now you will have the data as a part of request.POST QueryDict.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With