5

我是 Backbone.js 的新手,我正在尝试保存模型实例。我正在使用 django 作为我的服务器。

客户端代码:

var Song = Backbone.Model.extend({
    defaults: {
        name: 'New Song'
    },
    url: function() {
        return window.location.href;
    }

});

var song = new Song()
song.save()

csrfmiddlewaretoken在发送数据之前正确设置。

我单步执行了 Backbone.sync 内部调用的 jQuery $.ajax 函数,发现模型对象包含正确的数据。

但是,request.POST服务器收到的是

POST:<QueryDict: {u'[object Object]': [u'']}>

而不是实际数据。知道我哪里出错了吗?

更新:我通过设置Backbone.emulateJSON为 true 进行了快速修复。但根据 Backbone (0.9.2) 代码中的注释,它适用于旧版服务器。我正在使用 Django 1.4.1。这是否意味着 django 1.4.1 不兼容?

更新 2:当我设置Backbone.emulateJSON为 时false,我在 Firefox 中收到以下错误,但它在 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]"

我正在使用 jQuery 作为 Backbone 首选的 ajax,似乎错误可能在 jQuery 中。

更新 3:我通过用我自己的覆盖 Backbone.sync 使用的 $.ajax 来解决它。它仍然是一个快速修复。

Backbone.js 版本:0.9.2

jQuery 版本:1.8.0。还尝试了 1.7.2。结果相同。

4

2 回答 2

9

我遇到了类似的问题,通过一些侦探工作/运气我发现了。问题是,默认情况下,Backbone 将 POST 数据作为请求正文中的 JSON 编码字符串发送,而不是作为request.POSTQueryDict 的一部分。因此,要在这种情况下获取数据,您必须使用 python json 库并json.loads(request.body)在 Django 视图中调用以正确读取数据。

顺便说一句,设置Backbone.emulateJSON = true;起作用的原因是因为 Backbone 通过“遗留”机制将 JSON 发送到 Django,这使得它出现在request.POSTQueryDict 中。

于 2013-04-11T04:16:33.537 回答
1

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.

于 2014-09-08T18:59:01.520 回答