I'm working on some code that relies on Backbone, Backbone-relational and Tastypie working together. (If it matters, I've included the backbone-tastypie library).
I have a Basket
model that stores some properties about itself, and can HaveMany Fruit
models:
var Fruit = Backbone.RelationalModel.extend({
urlRoot: '/api/v1/fruit/',
});
var Basket = Backbone.RelationalModel.extend({
urlRoot: '/api/v1/basket/',
relations: [{
type: Backbone.HasMany,
key: 'fruit',
relatedModel: Fruit,
reverseRelation: {
key: 'basket',
includeInJSON: 'id',
}
}],
});
var BasketCollection = Backbone.Collection.extend({
model: Basket,
});
I start by loading all my baskets:
var baskets = new BasketCollection();
baskets.fetch();
That works great because I've configured Tastypie to automatically include the fruit along with the baskets. Here's what the resources look like:
class BasketResource(ModelResource):
fruit = fields.ToManyField('my.api.resources.FruitResource', 'fruit', full=True)
class Meta:
queryset = Basket.objects.all()
class FruitResource(ModelResource):
basket = fields.ForeignKey(BasketResource, 'basket')
class Meta:
queryset = Fruit.objects.all()
The issue comes when trying to save a fruit. Let's say fruit
represents an already existing fruit that was fetched.
fruit.set('eaten', true);
fruit.save();
Tastypie gives a Bad Request error because when Backbone serializes the fruit
object for sending, it sets its basket
property set to a number (the ID of the basket).
The full response from Tastypie is:
{"error": "The 'basket' field was given data that was not a URI, not a dictionary-alike and does not have a 'pk' attribute: 1."}
I don't want to have to manually set the basket property to an object with a PK field, or the data URI before I save the models. That defeats the point of it working seamlessly. Is there a way to tell Tastypie that when it receives a number, it's the ID of the basket?
Edit: Instead of making Tastypie accept raw IDs, it may be more reasonable to tweak Backbone's logic to use the resource_uri instead of the id during serialization. Is there a way to do this?
I apparently missed a fairly important detail. In the reverseRelation
I set includeInJSON
to 'id'
. It is specifically used to pull a specific value when serializing.
It works by changing includeInJSON
to 'resource_uri'
.