Including child resources in the Django Tastypie API

I am planning a site with Django and Tastypie for the REST API, and it’s hard for me to determine how to properly include child resources in the returned resource.

As a sandbox, I made a small application with a ticket model and TicketComment model, where comments belong to tickets. I looked at the Tastipi recipe for invested resources (http://django-tastypie.readthedocs.org/en/latest/cookbook.html#nested-resources), but I can hardly understand why I should do this. The code below uses django.forms.models.model_to_dict () to get the comments on the ticket, but I think there should be a "gotcha" somewhere here.

Is there a reason why I should not do what I am doing now? Also, is there a cleaner model for this than what is stated in the cookbook?

The models are as follows:

# tickets/models.py from django.db import models class Ticket(models.Model): title = models.CharField(max_length=200) create_ts = models.DateTimeField(auto_now_add=True) submitter_email = models.EmailField() PRIORITY_CHOICES = ( ('H', 'High'), ('M', 'Medium'), ('L', 'Low'),) priority = models.CharField(max_length=1, choices=PRIORITY_CHOICES) description = models.TextField() STATUS_CHOICES = ( ('NEW', 'New & Unclaimed'), ('WIP', 'Work In Progress'), ('RES', 'Resolved'), ('CLS', 'Closed'),) status = models.CharField(max_length=3, choices=STATUS_CHOICES) def __unicode__(self): return "<Ticket:%d:%s>" % (self.id, self.title,) class TicketComment(models.Model): ticket = models.ForeignKey(Ticket) comment_ts = models.DateTimeField(auto_now_add=True) commenter_email = models.EmailField() comment = models.TextField() def __unicode__(self): return "<TicketComment:%d:%d>" % (self.ticket.id, self.id,) 

Resources:

 # tickets/api.py from tastypie import fields from tastypie.resources import ModelResource from tickets.models import Ticket, TicketComment from django.forms.models import model_to_dict class TicketResource(ModelResource): class Meta: queryset = Ticket.objects.all() resource_name = 'ticket' def dehydrate(self, bundle): comments = TicketComment.objects.filter(ticket=bundle.data['id']) bundle.data['comments'] = [model_to_dict(c) for c in comments] return bundle class TicketCommentResource(ModelResource): ticket = fields.ForeignKey(TicketResource, 'ticket') class Meta: queryset = TicketComment.objects.all() resource_name = 'comment' 

The output is as follows:

 { comments: [ { comment: "This is the first comment.", commenter_email: "me@example.com", id: 1, ticket: 1 }, { comment: "This is the second comment.", commenter_email: "me@example.com", id: 2, ticket: 1 } ], create_ts: "2011-10-17T15:55:11.372000", description: "This is the first ticket.", id: "1", priority: "M", resource_uri: "/api/v1/ticket/1/", status: "NEW", submitter_email: "me@example.com", title: "First Ticket" } 
+8
python rest api django tastypie
source share
2 answers
+14
source share

Can you post your solution?

I have the same usage / model example (the foreign key relationship relationship set in the "child table" pointing back to the parent table) but cannot solve the problem.

The solution I saw is to add this line to your TicketResource class level NOT inside the metaclass:

 comments = fields.ToManyField('TicketCommentResource', 'ticket', full=True) 

Then, perhaps also add this to TicketCommentResource again at the class level:

 event = fields.ForeignKey('TicketResource', 'event') 

But I always get the error that my parent resource of the object (in your TicketResource example) does not have the ticket attribute, which is the second term sent to ToManyField.

I tried to play with this a lot, but it seems that I am not getting a winning combination. The solution that you originally uploaded works, but, as you yourself pointed out, it is not perfect.

Thanks!

+1
source share

All Articles