rookieRailer
rookieRailer

Reputation: 2341

Tastypie Reverse Relation

I am trying to get my api to give me the reverse relationship data with tastypie.

I have two models, DocumentContainer, and DocumentEvent, they are related as:

DocumentContainer has many DocumentEvents

Here's my code:

class DocumentContainerResource(ModelResource):
    pod_events = fields.ToManyField('portal.api.resources.DocumentEventResource', 'pod_events')
    class Meta:
        queryset = DocumentContainer.objects.all()
        resource_name = 'pod'
        authorization = Authorization()
        allowed_methods = ['get']

    def dehydrate_doc(self, bundle):
        return bundle.data['doc'] or ''

class DocumentEventResource(ModelResource):

    pod = fields.ForeignKey(DocumentContainerResource, 'pod')
    class Meta:
        queryset = DocumentEvent.objects.all()
        resource_name = 'pod_event'
        allowed_methods = ['get']

When I hit my api url, I get the following error:

DocumentContainer' object has no attribute 'pod_events

Can anyone help?

Thanks.

Upvotes: 7

Views: 2878

Answers (2)

I made a blog entry about this here: http://djangoandlove.blogspot.com/2012/11/tastypie-following-reverse-relationship.html.

Here is the basic formula:

API.py

class [top]Resource(ModelResource):
    [bottom]s = fields.ToManyField([bottom]Resource, '[bottom]s', full=True, null=True)
    class Meta:
        queryset = [top].objects.all()

class [bottom]Resource(ModelResource):
    class Meta:
        queryset = [bottom].objects.all()

Models.py

class [top](models.Model):
    pass

class [bottom](models.Model):
    [top] = models.ForeignKey([top],related_name="[bottom]s")

It requires

  1. a models.ForeignKey relationship from the child to the parent in this case
  2. the use of a related_name
  3. the top resource definition to use the related_name as the attribute.

Upvotes: 12

sampson-chen
sampson-chen

Reputation: 47267

Change your line in class DocumentContainerResource(...), from

pod_events = fields.ToManyField('portal.api.resources.DocumentEventResource', 
                                'pod_events')

to

pod_events = fields.ToManyField('portal.api.resources.DocumentEventResource', 
                                'pod_event_set')

The suffix for pod_event in this case should be _set, but depending on the situation, the suffix could be one of the following:

  • _set
  • _s
  • (no suffix)

If each event can only be associated with up to one container, also consider changing:

pod = fields.ForeignKey(DocumentContainerResource, 'pod')

to:

pod = fields.ToOneField(DocumentContainerResource, 'pod')

Upvotes: 1

Related Questions