Call django rest API with list of model ids

2019-07-01 14:35发布

问题:

I'm trying to figure out the best way to go about querying an endpoint for specific models with a list of those model ids. I know that I can query the detail endpoint using the id in the url (/markers/{id}), but I'd like to be able to post multiple ids at once and receive data from the model instances with those ids. As of right now, I created a custom APIView seen below (MarkerDetailsList) where I essentially just post a list of ids and define a custom post method to parse and lookup the ids in the db, but I'm finding it hard to believe this is the best way to accomplish this. Is there a way to achieve the same thing using the viewset? I've checked the documentation and searched around and cant seem to find anything. Any suggestions?

class MarkerViewSet(viewsets.ModelViewSet):
    permission_classes = [permissions.AllowAny]
    authentication_classes = ()
    queryset = Marker.objects.all()
    serializer_class = MarkerSerializer

class MarkerDetailList(APIView):
    queryset = Marker.objects.all()
    serializer_class = MarkerSerializer
    permission_classes = [permissions.AllowAny]
    authentication_classes = (JSONWebTokenAuthentication, )

    def post(self, request):
        ids = request.data['mapIds']
        markers = Marker.objects.filter(id__in=ids)
        serializer = MarkerSerializer(markers, many=True)
        return Response(serializer.data)

回答1:

You could use a Filter and FilterSet for this. (Wrote part of the code, then found https://stackoverflow.com/a/24042182/2354734)

class ListFilter(django_filters.Filter):
    def filter(self, qs, value):
        if value not in (None, ''):
            integers = [int(v) for v in value.split(',')]
            return qs.filter(**{'%s__%s'%(self.name, self.lookup_type):integers})
        return qs  

class MarkerFilter(django_filters.FilterSet):
    ids = django_filters.NumberFilter(name="id", lookup_type='in')

    class Meta:
        model = Marker
        fields = ['ids']

class MarkerViewSet(viewsets.ModelViewSet):
    queryset = Marker.objects.all()
    serializer_class = MarkerSerializer
    filter_backends = (filters.DjangoFilterBackend,)
    filter_class = MarkerFilter

When you now retrieven on /markers/?ids=1,2,3,4