[Fixed]-Django REST framework: Can a nested object access its parent object's details in a List View?

18👍

Moment of clarity: the solution is to use a SerializerMethodField to instantiate the RepSummarySerializer and pass the customer_id in the context:

class CustomerSummarySerializer(serializers.HyperlinkedModelSerializer):
    id = ...
    name = ...
    rep = serializers.SerializerMethodField('get_rep')


    def get_rep(self, obj):
        rep = obj.rep
        serializer_context = {'request': self.context.get('request'),
                              'customer_id': obj.id}
        serializer = RepSummarySerializer(rep, context=serializer_context)
        return serializer.data

The customer_id can now be accessed in RepSummarySerializer.get_rep_url like this:

def get_rep_url(self, obj):
    customer_id = self.context.get('customer_id')
    ...

Don’t know why I didn’t think of this three hours ago.

2👍

In addition to the accepted answer, if you use viewsets and want your sub-resource to be a collection (filtered by the parent document) only, you can also use the @detail_route decorator, as documented in the docs:

from rest_framework import viewsets
from rest_framework.decorators import detail_route
from rest_framework.response import Response

class CustomerViewSet(viewsets.ModelViewSet):
    queryset = Customer.objects.all()
    serializer_class = CustomerSummarySerializer

    ...

    @detail_route(methods=['get'])
    def rep(self, request, pk=None):
        customer = self.get_object()
        queryset = customer.pk.all()
        instances = self.filter_queryset(queryset)
        serializer = RepSummarySerializer(instances,
                context={'request': request}, many=True)
        return Response(serializer.data)

Now you can query /customers/123/rep/ and you will get a list of all Rep instances for the specified customer.

It probably won’t fully solve what you need, but for many people that don’t need full nested resources it’s actually enough.

Leave a comment