Backbone model.save() is causing POST not PUT

2019-02-17 02:46发布

I have a Backbone model:

var User = Backbone.Model.extend({
  idAttribute: '_id',

  url: '/api/user',

  defaults:
    { username: ''
    }
});

I fetch it:

var user = new User();

user.fetch();

Now, as an click event in one of my views, I have this:

toggleSubscription: function () {
  user.set('subscriptions', true);
  user.save();
}

This causes a POST request. However, the record already exists on the server, and since I fetched it (and the model instance has an id property), I thought that Backbone should do a PUT instead of a POST. Why might it be doing a POST instead?

标签: backbone.js
5条回答
爱情/是我丢掉的垃圾
2楼-- · 2019-02-17 02:56

Try checking user.isNew().

Looks like you created a new model which does not have an ID, that's why it's trying to add it during Backbone.sync.

UPDATE:

Above is exactly true. It does POST because it's a new model (which means, it does not have an id). Before you fetch a model, you need to give it an id. In your example:

var user = new User();
user.fetch();
user.save(); // in XHR console you see POST

var user = new User({ id: 123 });
user.fetch();
user.save(); // in XHR console you see PUT
查看更多
Ridiculous、
3楼-- · 2019-02-17 03:00

It may be worth checking if maybe emulateHTTP is true. This will change all your PUT into POST with an added _method header (you may also want to check that this exists to confirm the idea).

查看更多
ゆ 、 Hurt°
4楼-- · 2019-02-17 03:03

if the model does not yet have an id, it is considered to be new. --http://backbonejs.org/#Model-isNew

if the model does not yet have an id, it is considered to be new... AND therefore backbone will do a PUT request rather than a POST.

This behavior can be overridden simply by adding type: 'POST' to your save block:

var fooModel = new Backbone.Model({ id: 1});

fooModel.save(null, {
  type: 'POST'
});
查看更多
兄弟一词,经得起流年.
5楼-- · 2019-02-17 03:04

The server response must be in this way:

{
  _id : 111
}

Because you set _id as the primary key. When model is fetched verify the value of _id it must have a value: console.log( model.get('_id') );

My thought is that you set in your backbone model '_id' as primary key, but service is returning you 'id'

Update: Adding sample code of normal behavior:

var UserModel = Backbone.Model.extend({
  idAttribute: '_id',

  url: '/api/user',

  defaults:
    { username: ''
    }
});
user = new UserModel({_id : 20});
user.save();
user = new UserModel();
user.save();

Output: PUT /api/user 405 (Method Not Allowed) POST /api/user 404 (Not Found)

Check how the first instance of the Model has an id and it tries to do the PUT but the other POST. I cannot reproduce your issue, so my thought is that the problem is on your server response.

查看更多
戒情不戒烟
6楼-- · 2019-02-17 03:18

Use urlRoot property to set base URL /api/user. Then

  1. it will POST to /api/user when you save a model which doesn't have _id property set and
  2. it will PUT to /api/user/{_id} when you save a model which has _id property set. Notice that it automatically appends _id value to the base URL.

It will look for value of _id property because you have set that value to idAttribute.

查看更多
登录 后发表回答