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

前端 未结 2 1201
清酒与你
清酒与你 2021-02-04 03:40

I am attempting to implement a nested resource where one of its fields depends on a value from its parent resource.

Suppose we are building a system for a company which

相关标签:
2条回答
  • 2021-02-04 04:35

    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.

    0 讨论(0)
  • 2021-02-04 04:39

    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.

    0 讨论(0)
提交回复
热议问题