【问题标题】:Saving Backbone.js model data. Data not sent correctly保存 Backbone.js 模型数据。数据未正确发送
【发布时间】:2012-08-25 14:28:20
【问题描述】:

我是 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 在发送数据之前已正确设置。

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

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

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

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

更新:我通过将 Backbone.emulateJSON 设置为 true 进行了快速修复。但根据 Backbone (0.9.2) 代码中的 cmets,它适用于旧版服务器。我正在使用 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。结果一样。

【问题讨论】:

  • 您能否查看您的网络面板并查看正在发布到您的服务器的数据。我对 Django 不熟悉,但您的问题绝对看起来像是服务器端问题,而不是 Backbone 的问题。
  • @TyroneMichael 感谢您的建议。 chrome 中的网络面板显示模型是作为请求有效负载中的普通对象发送的。但在 Firefox 中,我收到了 Update 2 中写的错误。
  • 我不认为数据是作为字符串发送的(看看here)。当 Emulate JSON 为 false 时,您会收到此错误吗?当您注释掉 Emulate JSON = false 时,FF 中会发生什么?
  • @Pramod:查看below 发布的解决方案。可以覆盖 Backbone.sync 以获取 request.POST QueryDict 中的模型数据。

标签: jquery ajax django backbone.js


【解决方案1】:

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

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

【讨论】:

  • ...或 json.loads(request.raw_post_data) 用于旧版本的 django
【解决方案2】:

如果您希望数据在 QueryDict request.POST 中可用,则必须重写 Backbone.sync 方法。

首先,您必须将 Backbone.emulateJSON 设置为 true。

您可以查看 here 上的 Backbone.sync 方法。您会注意到模型属性是字符串化的。

if (options.data == null && model && (method === 'create' || method === 'update' || method === 'patch')) {
  params.contentType = 'application/json';
  params.data = JSON.stringify(options.attrs || model.toJSON(options));
}

将这部分函数编辑为:

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));
  }
}

在另一行,您会注意到 Backbone 向 POST QueryDict 添加了一个“模型”键。

params.data = params.data ? {model: params.data} : {};

将此行编辑为:

params.data = params.data ? params.data : {};

就是这样!现在您将数据作为 request.POST QueryDict 的一部分。

【讨论】:

    猜你喜欢
    • 2012-04-06
    • 2013-04-16
    • 2013-04-26
    • 1970-01-01
    • 2015-11-13
    • 1970-01-01
    • 2018-05-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多