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

基于类视图的Django过滤器:动态应用Django过滤器集

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

    我正在使用 django-filters filter_class 对视图集进行初始过滤的基于类的视图。我有一个单独的过滤器,根据需要过滤输出。

    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))
    
    class FilterOne(filters.FilterSet):
        title = filters.CharFilter(method=filter_booking_title)
    
        class Meta:
            model = models.Booking
            fields = [
                'title',
                'state',
                'client',
            ]
    
    
    class FilterTwo(filters.FilterSet):
        client = filters.ModelMultipleChoiceFilter(queryset=users_models.Client.objects.all())
    
        state = filters.MultipleChoiceFilter(choices=constants.BookingState)
    
        camera_operator = filters.ModelMultipleChoiceFilter(queryset=users_models.UserManager.camop_users())
    
        date_start = filters.DateFilter(name='date', lookup_expr='startswith')
    
        date_end = filters.DateFilter(name='date', lookup_expr='endswith')
    
        class Meta:
            model = models.Booking
            fields = [
                'state',
                'client',
                'camera_operator',
                'date_start',
                'date_end',
            ]
    

    api.py公司

    class MyViewSet(
        MultipleSerializerMixin,
        mixins.CreateModelMixin,
        mixins.RetrieveModelMixin,
        mixins.UpdateModelMixin,
        mixins.ListModelMixin,
        viewsets.GenericViewSet
    ):
        lookup_field = 'uuid'
        queryset = models.Booking.objects.all()
        filter_backends = [filters.BookingFilterBackend, DjangoFilterBackend, ]
        filter_class = filters.FilterOne
        pagination_class = BookingViewSetPagination
        serializer_class = serializers.BookingDetailSerializer
    
        serializer_classes = {
            ...            
        }
    
        @list_route(methods=['POST'], url_path='export-bookings')
        def export_bookings(self, request, *args, **kwargs):
        queryset = self.get_queryset()
    
        // just some debugging code
        query_dict = request.data
        print(query_dict.get('state', []))
        print(query_dict.get('clients', []))
        print(query_dict.get('camera_operators', []))
        print(query_dict.get('from_date', ''))
        print(query_dict.get('to_date', ''))
    
        // Apply the filter set - FilterTwo - on my model objects -> Booking. Something like this:
        // filtered_queryset = filters.FilterTwo(queryset, query_dict) - ??
    
        return response.NoContent()
    

    但是,我不知道如何编写调用 FilterTwo 具有 the query dictionary (在电话会议正文中收到)和原件 queryset .

    其次,我有一个 date 字段,我想在这个字段上执行大于和小于。我想知道我的过滤逻辑写得是否正确。

    2 回复  |  直到 7 年前
        1
  •  3
  •   aman kumar    7 年前

    您可以调用filter类filter\u queryset方法

     queryset = self.get_queryset()
     queryset = self.filter_queryset(queryset)
    
        2
  •  1
  •   saran3h    7 年前

    最后,在深入研究了django滤袋和 django_filters

    这就是解决方案: 而不是定义一个新的习惯 FilterSet FilterBackend 并覆盖 filter_queryset 方法。

    过滤器.py

    from django.db.models import Q
    from django_filters import rest_framework as filters
    from dry_rest_permissions.generics import DRYPermissionFiltersBase
    from rest_framework import filters as generic_filters
    
    # Project Local
    from . import models, constants
    from shootsta.users import models as users_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))
    
    # This is my new filter backend (I know the filtration logic looks very basic, I've come from a java background so spare me the rant.)
    class MyNewFilterBackend(generic_filters.BaseFilterBackend):
        def filter_queryset(self, request, queryset, view):
            predicate = request.data
    
            if all(k in predicate for k in ('from_date', 'to_date')):
                queryset = queryset.filter(date__range=(predicate['from_date'], predicate['to_date']))
    
            if 'from_date' in predicate and 'to_date' not in predicate:
                queryset = queryset.filter(date__gte=predicate['from_date'])
    
            if 'to_date' in predicate and 'from_date' not in predicate:
                queryset = queryset.filter(date__lte=predicate['to_date'])
    
            if 'state' in predicate:
                queryset = queryset.filter(state__in=predicate['state'])
    
            if 'clients' in predicate:
                queryset = queryset.filter(client__in=predicate['clients'])
    
            if 'camera_operators' in predicate:
                queryset = queryset.filter(camera_operator__uuid__in=predicate['camera_operators'])
    
            if 'recipients' in predicate:
                queryset = queryset.filter(users__uuid__in=predicate['recipients'])
    
            return queryset
    

    这是我的api.py,我刚刚将这个新的过滤器后端添加到列表中。

    api.py公司

    class MyViewSet(
        MultipleSerializerMixin,
        mixins.CreateModelMixin,
        mixins.RetrieveModelMixin,
        mixins.UpdateModelMixin,
        mixins.ListModelMixin,
        viewsets.GenericViewSet
    ):
    
    ...
    
    filter_backends = [filters.BookingFilterBackend, filters. MyNewFilterBackend, DjangoFilterBackend, ]
    ...
    
    
    # This is the api which receives filteration form data from frontend.
    @list_route(methods=['POST'], url_path='export-bookings')
    def export_bookings(self, request, *args, **kwargs):
        queryset = self.get_queryset()
    
        # filter results!
        filtered_queryset = self.filter_queryset(queryset)
    
        tasks.generate_export_data_and_notify_accounts(filtered_queryset)
    
        return response.NoContent()
    

    我仍然在想我是否可以用FilterSets实现这一点。

    推荐文章