# How to prefetch related objects in Django Tastypie resources

# TLDR

You just need to use Django's prefetch_related (opens new window) as usual on the resource's queryset attribute. For example:




 

class UserResource(ModelResource):
    jobs = fields.ToManyField(JobResource, 'jobs', full=True)
    class Meta:
        queryset = User.objects.prefetch_related('jobs').all()
1
2
3
4

# Background

Django Tastypie allows you to add relationship fields (opens new window)
to resources (opens new window) which will let Tastypie return related objects in its response.

For example, we might want to return all of the user's jobs along with the user itself:


 



class UserResource(ModelResource):
    jobs = fields.ToManyField(JobResource, 'jobs', full=True)
    class Meta:
        queryset = User.objects.all()
1
2
3
4

The response will be something like:

{
  "meta": {
    ...
    "total_count": 2
  },
  "objects": [
    {
      "first_name": "Test",
      "last_name": "Example",
      "jobs": [
        {
          "id": 1,
          "resource_uri": "/api/v1/job/1/",
          "title": "Job 1"
        },
        {
          "id": 2,
          "resource_uri": "/api/v1/job/2/",
          "title": "Job 2"
        }
    },
    ...
  ]
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

However, if we're not careful, relationship fields can add tons of extra database queries.

Django's prefetch_related (opens new window) method for querysets allows us to "prefetch" related objects by fetching them all in one query instead of one-by-one.

# Prefetching in Tastypie resources

I thought that Tastypie might have built-in support for prefetching related objects, but it does not. You simply need to alter the queryset attribute of your resource and use prefetch_related as you would normally in Django:




 

class UserResource(ModelResource):
    jobs = fields.ToManyField(JobResource, 'jobs', full=True)
    class Meta:
        queryset = User.objects.prefetch_related('jobs').all()
1
2
3
4

Sometimes you might want to return sub-relationships as well. For example, you might want to fetch all of the users with all of their jobs plus the locations of their jobs. You can then add the sub-relationship to the prefetch_related call as well:









 

class JobResource(ModelResource):
    locations = fields.ToManyField(LocationResource, 'locations', full=True)
    class Meta:
        queryset = Job.objects.all()

class UserResource(ModelResource):
    jobs = fields.ToManyField(JobResource, 'jobs', full=True)
    class Meta:
        queryset = User.objects.prefetch_related('jobs__locations').all()
1
2
3
4
5
6
7
8
9

Newsletter

If you'd like to subscribe to my blog, please enter your details below. You can unsubscribe at any time.

Powered by Buttondown.

Last Updated: 11/20/2023, 10:04:51 AM