Search code examples
djangobackbone.jstastypiebackbone-relational

Backbone model save() with Django Tastypie


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?


Solution

  • 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'.