代码之家  ›  专栏  ›  技术社区  ›  saran3h

Django rest框架和GenericViewSet:基于url中的查询参数筛选结果

  •  0
  • saran3h  · 技术社区  · 7 年前

    我的应用程序将GenericViewSet与ListModelMixin一起使用。我用过 filter_backends filter_class “列表”:serializers.BookingListSerializer

    enter image description here

    我正在编写以下摘要:

    假设我有一个预先过滤的动物列表(使用 )然后在UI上显示给用户。

    1. 用户可以根据UI中的一些搜索条件(比如名称、类型、颜色)进一步过滤结果。这些过滤由 筛选器\u类 .

    2. 而不是所有的动物。也可以根据名称和颜色进一步过滤。

    animals dogs 使用相同的django模态,filter backends和filter class只应用于实际模态,即动物列表上的模态。

    def list1(request) def list2(request) 在那里我可以过滤 query_set

    api.py公司

    class BookingViewSet(
    MultipleSerializerMixin,
    mixins.CreateModelMixin,
    mixins.RetrieveModelMixin,
    mixins.UpdateModelMixin,
    mixins.ListModelMixin,
    viewsets.GenericViewSet
    ):
    lookup_field = 'uuid'
    queryset = models.Booking.objects.all()
    permission_classes = [DRYPermissions, ]
    filter_backends = [filters.BookingFilterBackend, DjangoFilterBackend, ]
    filter_class = filters.BookingFilter
    pagination_class = BookingViewSetPagination
    serializer_class = serializers.BookingDetailSerializer
    
    serializer_classes = {
        'create': serializers.BookingCreateUpdateSerializer,
        'update': serializers.BookingCreateUpdateSerializer,
        'duplicate': serializers.BookingCreateUpdateSerializer,
        'list': serializers.BookingListSerializer,
        'list_drafts': serializers.BookingListSerializer,
        'create_draft': serializers.BookingCreateUpdateSerializer,
        'submit_draft': serializers.BookingCreateUpdateSerializer,
    }
    
    def create(self, request, *args, **kwargs):
        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)
    
        booking = services.create_booking(serializer.validated_data)
        data = serializers.BookingDetailSerializer(booking, context={'request': request}).data
    
        return response.Created(data)
    
    def update(self, request, *args, **kwargs):
        booking = self.get_object()
    
        partial = kwargs.pop('partial', False)
        serializer = self.get_serializer(booking, data=request.data, partial=partial)
        serializer.is_valid(raise_exception=True)
    
        booking = services.update_booking(booking, serializer.validated_data)
    
        async('shootsta.bookings.tasks.booking_update_google_calendar_event', booking.pk)
    
        data = serializers.BookingDetailSerializer(booking, context={'request': request}).data
    
        return response.Ok(data)
    
    @detail_route(methods=['POST'], url_path='duplicate')
    def duplicate(self, request, *args, **kwargs):
        booking = self.get_object()
    
        new_booking = services.duplicate_booking(booking)
    
        data = serializers.BookingDetailSerializer(new_booking, context={'request': request}).data
    
        return response.Created(data)
    
    @list_route(methods=['GET'], url_path='list-drafts')
    def list_drafts(self, request, *args, **kwargs):
        # Code goes here! Here i'll get some params from url like state and title and then return filtered the results.
        pass
    
    @list_route(methods=['POST'], url_path='create-draft')
    def create_draft(self, request, *args, **kwargs):
        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)
    
        booking = services.create_booking(serializer.validated_data, constants.BookingMode.draft)
        data = serializers.BookingDetailSerializer(booking, context={'request': request}).data
    
        return response.Created(data)
    
    @detail_route(methods=['POST'], url_path='submit-draft')
    def submit_draft(self, request, *args, **kwargs):
        booking = self.get_object()
        booking.submit_draft(by=request.user)
        booking.save()
    
        data = serializers.BookingDetailSerializer(booking, context={'request': request}).data
    
        return response.Ok(data)
    
    @detail_route(methods=['POST'], url_path='approve')
    def approve(self, request, *args, **kwargs):
        booking = self.get_object()
        booking.approve(by=request.user)
        booking.save()
    
        data = serializers.BookingDetailSerializer(booking, context={'request': request}).data
    
        return response.Ok(data)
    

    过滤器.py

    # Standard Library
    import operator
    from functools import reduce
    
    # Third Party
    from django.db.models import Q
    from django_filters import rest_framework as filters
    from dry_rest_permissions.generics import DRYPermissionFiltersBase
    
    # Project Local
    from . import models
    
    
    class BookingFilterBackend(DRYPermissionFiltersBase):
        def filter_list_queryset(self, request, queryset, view):
            if request.user.is_role_admin:
                return queryset
    
            if request.user.is_role_client:
                return queryset.filter(Q(client=request.user.client))
    
            if request.user.is_role_camop:
                return queryset.filter(Q(camera_operator=request.user))
    
            return queryset.filter(Q(created_by=request.user))
    
    
    def filter_booking_title(queryset, name, value):
        """
        Split the filter value into separate search terms and construct a set of queries from this. The set of queries
        includes an icontains lookup for the lookup fields for each of the search terms. The set of queries is then joined
        with the OR operator.
        """
        lookups = ['title__icontains', ]
    
        or_queries = []
    
        search_terms = value.split()
    
        for search_term in search_terms:
            or_queries += [Q(**{lookup: search_term}) for lookup in lookups]
    
        return queryset.filter(reduce(operator.or_, or_queries))
    
    
    class BookingFilter(filters.FilterSet):
        title = filters.CharFilter(method=filter_booking_title)
    
        class Meta:
            model = models.Booking
            fields = [
                'title',
                'state',
                'client',
            ]
    
    2 回复  |  直到 7 年前
        1
  •  2
  •   JPG    7 年前
    class SampleViewset(.....):
    
        @list_route(methods=['GET'])
        def list_2(self, request, *args, **kwargs):
            myqueryset = MyModel.objects.all() # or whatever queryset you need to serialize
            queryset = self.filter_queryset(myqueryset)
    
            page = self.paginate_queryset(queryset)
            if page is not None:
                serializer = self.get_serializer(page, many=True)
                return self.get_paginated_response(serializer.data)
    
            serializer = self.get_serializer(queryset, many=True)
            return Response(serializer.data)


    你应该注意的要点是,

    1内部正在执行过滤过程 self.filter_queryset() QuerySet 应用过滤器后。
    2你可以用 self.get_queryset() myqueryset = MyModel.objects.all() staement,这是 做这样的事

    更新-1
    queryset ,你可以用 get_queryset() 方法as,

    class SampleViewset(.....):
    
        @list_route(methods=['GET'])
        def list_2(self, request, *args, **kwargs):
            queryset = self.filter_queryset(self.get_queryset())
    
            page = self.paginate_queryset(queryset)
            if page is not None:
                serializer = self.get_serializer(page, many=True)
                return self.get_paginated_response(serializer.data)
    
            serializer = self.get_serializer(queryset, many=True)
            return Response(serializer.data)


    class SampleViewset(.....):
    
        @list_route(methods=['GET'])
        def list_2(self, request, *args, **kwargs):
            return self.list(self, request, *args, **kwargs)
        2
  •  1
  •   Ehsan Nouri    7 年前

    filter_queryset 在初始查询中,例如:

    class your_view(....):
    ...
    ...
        def get_queryset2(self):
            return YourotherModel.objects.all() ### or any thing your i.e. specific fiter on your general model
    
    
        @action(methods=['GET'], detail=False)
        def list2(self, request, *args, **kwargs):
            queryset = self.filter_queryset(self.get_queryset2()) ### call filter_queryset on your custom query
    
            page = self.paginate_queryset(queryset)
            if page is not None:
                serializer = self.get_serializer(page, many=True)
                return self.get_paginated_response(serializer.data)
    
            serializer = self.get_serializer(queryset, many=True)
            return Response(serializer.data)
    
    推荐文章