来自Backbone's doc:
Backbone 已预先配置为与 RESTful API 同步。
[...]
默认的 sync handler 将 CRUD 映射到 REST,如下所示:
-
创建 →
POST /collection
-
阅读 →
GET /collection[/id]
-
更新 →
PUT /collection/id
-
补丁 →
PATCH /collection/id
-
删除 →
DELETE /collection/id
新条目没有 ID,因此如果您在保存模型之前为其提供 ID,Backbone 会默认为 PUT 请求,因为它认为您要保存现有条目。
如何使用 id 发起 POST 请求?
选择以下解决方案之一。
坚持使用 RESTful API
这是显而易见的。如果可以,请坚持标准。
更改 API 以处理 PUT/PATCH 请求,并且仅在创建时使用 POST。让 API 端点从 URL 中获取 ID。
RESTful API best practices
传递type 选项1
简单且非常适合一次性使用。
传递给save(或fetch)的每个选项都会覆盖sync函数默认定义的选项并传递给jQuery.ajax function。
Backbone sync source
// Make the request, allowing the user to override any Ajax options.
var xhr = options.xhr = Backbone.ajax(_.extend(params, options));
var url = model.url(); // get the url before setting the `id`
model.save({
id: somevalue
}, {
url: url, // fix the url
type: 'POST' // choose the HTTP verb
});
修复模型使用的url很简单,你也有一些选择:
重写 url 函数 (source) 适用于每次调用都应使用特定 url 而不附加默认 id 的情况。
var MyModel = Backbone.Model.extend({
url: function() {
return _.result(this, 'urlRoot') ||
_.result(this.collection, 'url') ||
urlError();
}
});
在模型上设置idAttribute
这取决于您尝试传递的 id 在数据中的含义。
Backbone 模型使用"id" 具有默认的id 属性名称。您可以通过覆盖模型的idAttribute property 来指定不同的名称。无论名称如何,它始终通过model.id property 自动提供。
现在,假设 id 属性与此模型无关,并且此模型的真实 id 属性名称类似于 UID,您可以更改模型的 idAttribute 以反映属性的真实名称(或者它甚至可以是一个永远不会成为属性的字符串)。
var MyModel = Backbone.Model.extend({
idAttribute: 'UID',
});
现在,id 属性不被视为当前模型的 id,model.isNew() 将返回 true,发送 POST 请求以在保存时创建它。
改变sync/save函数行为
如果您使用的 API 不是 RESTful,您可以通过覆盖sync function 来调整行为。这可以在模型或集合上完成,也可以在集合和模型默认使用的Backbone.sync function 上完成。
例如,如果您想让每个请求默认使用 POST 来处理 MyModel 类:
var MyModel = Backbone.Model.extend({
sync: function(method, model, options) {
return Backbone.sync.call(this, method, model,
_.extend({ type: 'POST' }, options));
}
});
您可以只使用 save 函数执行类似的操作,让 fetch 像往常一样执行其 GET 请求。
如果您想使用不支持的旧版 Web 服务器
Backbone 默认的 REST/HTTP 方式,你可以选择开启
Backbone.emulateHTTP。设置此选项将伪造PUT、PATCH 和
DELETE 使用 HTTP 请求 POST,设置 X-HTTP-Method-Override
标头与 true 方法。
[...]
Backbone.emulateHTTP = true;
model.save(); // POST to "/collection/id", with "_method=PUT" + header.
不要覆盖isNew
这个模型已经保存到服务器了吗?如果模型还没有
有一个id,就被认为是新的。
本网站上的其他一些答案建议覆盖isNew function。 不要。该函数有其目的,并且重写它以强制 POST 请求是一个糟糕的 hack,而不是解决方案。
isNew 在内部使用,但也可以由您的代码或其他库和 Backbone 插件使用。
1虽然我没有从堆栈溢出中获取它,但它已经是an answer by Andrés Torres Marroquín on a similar question。
2取自Maanas Royy's answer。