One to Many fields in Django Tastypie is easy if we search on Models on foward. Which we query from models who have Foreign Key. But, reverse query from related manager is a little bit complex. Because we know :
Unlike Django’s ORM, Tastypie does not automatically create reverse relations. This is because there is substantial technical complexity involved, as well as perhaps unintentionally exposing related data in an incorrect way to the end user of the API.
So, to make reverse Relationship with Django tastypie, we should define several things. Wrong things will lead you into this kind of error :
1 | reverse for ‘api_dispatch_detail’ with arguments ‘() |
To make reverse works, we should define both of Resource, URLS and pointing the relation models.
1. Models
I have “Places” APP, it have “School” models as manager and “Policy” as it related models.
models.py:
1 2 3 4 5 6 7 8 | from django.db import models class School(models.Model): name = models.CharField(unique=True, max_length=255) class Policy(models.Model): school = models.ForeignKey(School, related_name=’policies’) unit = models.CharField(null=True, max_length=255) |
2. Resource.
Now, i will define both of resource and linking them together for backward relationship.
api.py inside APP folder:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | from tastypie.authorization import DjangoAuthorization from tastypie.authentication import BasicAuthentication from tastypie.resources import ModelResource from places.models import School, Policy from tastypie import http, fields class SchoolResource(ModelResource): # fields.ToManyField(‘APP.api.RelatedResource’, ‘related name’) policies = fields.ToManyField(‘places.api.PolicyResource’, ‘policies’) class Meta: resource_name = ‘school’ queryset = School.objects.all() allowed_methods = [‘get’] authorization = DjangoAuthorization() authentication = BasicAuthentication() class PolicyResource(ModelResource): school = fields.ToOneField(SchoolResource, ‘school’) class Meta: queryset = Policy.objects.all() resource_name = ‘policy’ |
3. urls.py
Modify your PROJECT/urls.py :
1 2 3 4 5 6 7 8 9 10 11 12 13 | …. from places.api import SchoolResource, PolicyResource school_resource = SchoolResource() policy_resource = PolicyResource() urlpatterns = patterns(”, … # Including school resource API urls (r’^api/’, include(school_resource.urls)), (r’^api/’, include(policy_resource.urls)), …. ) |
Now when you search Schools, it will come with Policy related data :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | { "meta": { "limit": 20, "next": "/api/school/?offset=20&limit=20&format=json", "offset": 0, "previous": null, "total_count": 177 }, "objects": [ { "policies": [ "/api/policy/1/", "/api/policy/8/" ], "id": "2", "name": "Manhattan Public Schools", "resource_uri": "/api/school/2/" }, { "policies": [ "/api/policy/5/" ], "id": "4", "name": "Ohio Public Schools", "resource_uri": "/api/school/4/" }, |
How to make tastypie show all related models into manager models instead just API detail id? I will show you into the next articles 🙂