保存模型时如何强制POST请求?

时间:2016-12-11 19:46:40

标签: javascript rest backbone.js backbone-model

我需要对服务器端API进行POST。我必须将level_id密钥发送到服务器的请求正文中。

我使用的是Backbone模型。但是当我这样做时:

count

触发的网络请求是:id

Backbone没有POST但是PUT并将id附加到url。

所以我只想在没有Backbone注意的情况下将myModel.set("id", somevalue) myModel.save() 密钥传递给服务器。

1 个答案:

答案 0 :(得分:2)

来自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 endpoit从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 function

覆盖url函数(source)适用于每个调用都应使用特定网址而不附加默认id的情况。

var MyModel = Backbone.Model.extend({
    url: function() {
        return _.result(this, 'urlRoot') ||
            _.result(this.collection, 'url') ||
            urlError();
    }
});

在模型上设置idAttribute

这取决于您在数据中尝试传递的id内容。

Backbone Model使用"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 class:

var MyModel = Backbone.Model.extend({
    sync: function(method, model, options) {
        return Backbone.sync.call(this, method, model,
            _.extend({ type: 'POST' }, options));
    }
});

您可以执行与save功能类似的操作,让fetch像往常一样执行GET请求。

使用emulateHTTP setting 2

  

如果您想使用不支持的旧版Web服务器   Backbone的默认REST / HTTP方法,您可以选择打开   Backbone.emulateHTTP。设置此选项会假冒PUTPATCH和   使用HTTP DELETE的{​​{1}}次请求,设置POST   用真正的方法标题。

     

[...]

X-HTTP-Method-Override

不要覆盖Backbone.emulateHTTP = true; model.save(); // POST to "/collection/id", with "_method=PUT" + header.

  

此模型是否已保存到服务器了?如果模型还没有   有一个id,它被认为是新的。

本网站上的其他一些答案建议覆盖isNew function。的唐'吨即可。该函数有其目的并覆盖它以强制POST请求是一个糟糕的黑客,而不是解决方案。

isNew在内部使用,但您的代码或其他库以及Backbone插件也可以使用它。

1 虽然我没有从堆栈溢出中获取它,但它已经是an answer by Andrés Torres Marroquín on a similar question

2 取自Maanas Royy's answer