DRF filter 过滤器实现流程

佐手、 提交于 2020-02-28 04:20:29

关系

  • ListModelMixin
  • GenericAPIView(views.APIView).filter_queryset(queryset)

drf filters.py

  • BaseFilterBackend
  • SearchFilter(BaseFilterBackend)
  • OrderingFilter(BaseFilterBackend)
  • DjangoFilterBackend(metaclass=RenameAttributes)# django_filters.rest_framework.backends 官方filterdemo

1.入口queryset = self.filter_queryset(self.get_queryset())

views.py

class RecordView(MyModelViewSet):
    """
	user view
    """
    queryset = Record.objects.filter(status__gte=0)
    permission_classes = (permissions.IsAuthenticated, )
    filterset_class = RecordFilter # 定义过滤器
    serializer_map = {
        'create': AuthorizationRecordCreateSerializer,
    }
class ListModelMixin:
    """
    List a queryset.
    """
    def list(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 GenericAPIView(views.APIView):
	    queryset = None
		serializer_class = None

    	# If you want to use object lookups other than pk, set 'lookup_field'.
    	# For more complex lookup requirements override `get_object()`.
    	lookup_field = 'pk'
    	lookup_url_kwarg = None

    	# The filter backend classes to use for queryset filtering
    	filter_backends = api_settings.DEFAULT_FILTER_BACKENDS
	    def filter_queryset(self, queryset):
        """
        Given a queryset, filter it with whichever filter backend is in use.

        You are unlikely to want to override this method, although you may need
        to call it either from a list view, or from a custom `get_object`
        method if you want to apply the configured filtering backend to the
        default queryset.
        """
        for backend in list(self.filter_backends):
            queryset = backend().filter_queryset(self.request, queryset, self)
        return queryset
	
class DjangoFilterBackend(metaclass=RenameAttributes):
    filterset_base = filterset.FilterSet
    raise_exception = True
	
	def get_filterset(self, request, queryset, view):
			filterset_class = self.get_filterset_class(view, queryset) # 1.获取过滤器类
			if filterset_class is None:
				return None

			kwargs = self.get_filterset_kwargs(request, queryset, view) # 2.获取request.query_params过滤参数, 进行下一步过滤
			return filterset_class(**kwargs)											    # 3.实例化过滤器
	
	def get_filterset_class(self, view, queryset=None):
        """
        Return the `FilterSet` class used to filter the queryset.
        """
        filterset_class = getattr(view, 'filterset_class', None)  # views 用户定义
        filterset_fields = getattr(view, 'filterset_fields', None) # 

        # TODO: remove assertion in 2.1
        if filterset_class is None and hasattr(view, 'filter_class'):
            utils.deprecate(
                "`%s.filter_class` attribute should be renamed `filterset_class`."
                % view.__class__.__name__)
            filterset_class = getattr(view, 'filter_class', None)

        # TODO: remove assertion in 2.1
        if filterset_fields is None and hasattr(view, 'filter_fields'):
            utils.deprecate(
                "`%s.filter_fields` attribute should be renamed `filterset_fields`."
                % view.__class__.__name__)
            filterset_fields = getattr(view, 'filter_fields', None)

        if filterset_class:
            filterset_model = filterset_class._meta.model

            # FilterSets do not need to specify a Meta class
            if filterset_model and queryset is not None:
                assert issubclass(queryset.model, filterset_model), \
                    'FilterSet model %s does not match queryset model %s' % \
                    (filterset_model, queryset.model)

            return filterset_class

        if filterset_fields and queryset is not None:
            MetaBase = getattr(self.filterset_base, 'Meta', object)

            class AutoFilterSet(self.filterset_base):
                class Meta(MetaBase):
                    model = queryset.model
                    fields = filterset_fields

            return AutoFilterSet

        return None

    def get_filterset_kwargs(self, request, queryset, view): # 从request.query_parmas 获取过滤参数
        return {
            'data': request.query_params,
            'queryset': queryset,
            'request': request,
        }

    def filter_queryset(self, request, queryset, view): # APIView 入口
        filterset = self.get_filterset(request, queryset, view)
        if filterset is None:
            return queryset

        if not filterset.is_valid() and self.raise_exception:
            raise utils.translate_validation(filterset.errors)
        return filterset.qs
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!