Django-使用数组进行过滤和查询

问题描述 投票:0回答:4

我有一个简单的问题:目前我可以这样做从我的后端获取一个对象:

http://127.0.0.1:8000/api/v1/boats/boats?id=10
http://127.0.0.1:8000/api/v1/boats/boats?home_port=98&id=5

但是我想根据 ids 列表或 home_ports 列表获取一组船只,并且我已经尝试过:

http://127.0.0.1:8000/api/v1/boats/boats?id=10,11
http://127.0.0.1:8000/api/v1/boats/boats?id_in=10,11
http://127.0.0.1:8000/api/v1/boats/boats?id=10,id=11
http://127.0.0.1:8000/api/v1/boats/boats?id=10&id=11

但是这些都不起作用。使用 django-filter 执行此操作的最佳方法是什么,URL 规则是如何定义的?

这是我的观点:

class BoatList(generics.ListCreateAPIView):
    permission_classes = (IsOwnerOrReadOnly,)
    serializer_class = BoatSerializer
    queryset = Boat.objects.all()
    filter_backends = (filters.DjangoFilterBackend,)
    filter_fields = ('id', 'home_port',)

我标记为接受 100% 的解决方案回答了我的问题,但我最终根据我发现的使用过滤器的另一篇文章实现了不同的东西:

class ListFilter(Filter):

    def filter(self, qs, value):
        if not value:
            return qs

        self.lookup_type = 'in'
        values = value.split(',')
        return super(ListFilter, self).filter(qs, values)

class BoatFilter(FilterSet):
    ids = ListFilter(name='id')

    class Meta:
        model = Boat
        fields = ['home_port', 'ids']


class BoatList(generics.ListCreateAPIView):
    permission_classes = (IsOwnerOrReadOnly,)
    serializer_class = BoatSerializer
    queryset = Boat.objects.all()
    filter_backends = (filters.DjangoFilterBackend,)
    filter_class = BoatFilter

    def perform_create(self, serializer):
        serializer.save(owner=self.request.user)
python django api django-rest-framework django-filter
4个回答
8
投票

doniyor 给出的答案非常贴切。但我猜

request
在使用它的地方将不可用。

还有另一种方法可以做到这一点。您可以重写

get_queryset
方法。这可以按如下方式完成:

class BoatList(generics.ListCreateAPIView):
    permission_classes = (IsOwnerOrReadOnly,)
    serializer_class = BoatSerializer
    filter_backends = (filters.DjangoFilterBackend,)
    filter_fields = ('id', 'home_port',)

    def get_queryset(self):
        id_list = self.request.GET.getlist("id")
        if not id_list:
            return []
        return Boat.objects.filter(id__in=id_list)

4
投票

您只需创建一个过滤器类

    class NumberInFilter(BaseInFilter, NumberFilter):
          pass


    class myFilter(FilterSet):
          id__in = NumberInFilter(field_name='id', lookup_expr='in')

          class Meta:
                model = Boat

在视图集中使用

           filter_class = myFilter

你可以看到django-filter的这个文档: https://django-filter.readthedocs.io/en/master/ref/filters.html?highlight=BaseInFilter


3
投票

试试这个:

网址:

http://127.0.0.1:8000/api/v1/boats/boats?id=10,11

class BoatList(generics.ListCreateAPIView):
    permission_classes = (IsOwnerOrReadOnly,)
    serializer_class = BoatSerializer
    queryset = Boat.objects.filter(id__in=request.GET.getlist('id')) #<------
    filter_backends = (filters.DjangoFilterBackend,)
    filter_fields = ('id', 'home_port',)

0
投票

简单的解决方案如果您想使用数组,请创建过滤器集字段的对象。

filterset_fields = {'id':['exact'],'dist':['exact'],'data_type':['exact','in'], 'data_sub_type':['exact','in']}

现在让我们看看 data_sub_type 是否可以从邮递员那里发送一个列表。 数据类型__in =“1,2,3” 像这样

© www.soinside.com 2019 - 2024. All rights reserved.