Django tastypie One to Many fields related models reverse backward


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 🙂


Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.