I'm creating an Web-Application (Frontend and Backend, so both are under my control) using Backbone and Pyramid, being connected via a RESTful API.
During development I encountered a problem several times by now, where Backbone PUTs (=updates) a new model, while it actually should POST (=create) it.
Backbone decides whether to POST or UPDATE a model depending of the presence of an ID
-field (if no ID
present in the current model: -> POST/create | if so: PUT/update).
However I encountered several situations by now, where this behaviour doesn't match my application logic.
Let's say our main model (and its objects being persistently saved in a relational database in the backend) is called Foo
, having fields like id
, field_1
, field_2
.
Example #1 : Creating a template or preview of Foo
: Before creating (= POST
ing) an object of Foo
, I can create and show a preview to the user and/or save it as a template. While doing so, the backend (in case of the preview: temporarily) adds the object to the database and returns the full model - including an ID
in its HTTP response - back to Backbone. Template- and Preview-objects of Foo
are (temporarily) saved into the same table, as final objects (column type
indicates its type ( 0
= final/live, 1
= preview, 2
= template)). When now - after previewing / saving as template - trying to actually CREATE an object of Foo
, the Backbone model already has the ID
field set and actually PUT
s and updates the template or not-anymore-existing preview, instead of POST
ing and therewith creating a new Foo
inside the database (as intended).
=> solution #1 : calling POST /json/preview does not return the ID
field, so Backbone doesn't get confused.
=> solution #2 : overriding parse() of Foo in Backbone-model to kick out ID field from response
.=> kinda works
Example #2 : Having a Periodic
model, which refers to a Foo
-template. Intention of a Periodic
is to offer the user the possibility of semi-automatically creating a new Foo
object based on a Foo
-template every X months.
Now there is a call GET /json/periodics, which returns all Periodic
-objects with its nested Foo
-objects ( Foo
-templates), including their IDs, eg [{'interval': 12, template_id: 42, template: { 'id': 42, field_1: 'foo', field_2: 'bar', .. } , { .. } , .. ]
.
On the frontend the user now can periodically confirm (or skip) creating a new Foo
-object, by issuing: periodics[X].template.save()
which however again PUT
s and therewith updates the Foo
-model, instead of POST
ing and creating a new one (as intended).
Here again (as in example 1), I could strip out the ID
field of Foo
- either in the backend or frontend.
However there are situations, where I need the id
-field of templates, eg when actually editing them, so here I'd need two calls ( GET /json/templates_WITHOUT_FOO-IDs
and GET /json/templates_WITH_FOO-IDs
). which also sounds far from right.
Question is : What's the right (and consistent) way of avoiding Backbone falsely assuming a model should be PUT
instead of POST
ed in certain situations / views?
Backbone's save and fetch methods just make calls to the Backbone.sync method, which in turn is just a wrapper for an ajax call. you can pass in ajax parameters using the save function without having to actually extend it. basically ends up being something like this:
model.save({attributes you want to save}, {type:'POST', url: 'apiurl/model/:id/played'});
You would have to do this every time though so it is probably better practice to extend Backbone.sync for your model.
The Backbone website has a bit of information about what I'm talking about as far as the Backbone sync and save taking ajax options. There are also a few examples I've seen on extending sync but I can't seem to track them down at the moment.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.