drf中的filtering的源码分析和针对antp的protable的自定义修改

源码分析

    def filter_queryset(self, request, queryset, view):
    	# 获取咱们设定的待搜索的fields
        search_fields = self.get_search_fields(view, request)
        # 获取需要search的参数,默认为search,即去找url中的?search=xxx
        search_terms = self.get_search_terms(request)
		
		# 都没找到时就不过滤了
        if not search_fields or not search_terms:
            return queryset
		
		# 拼接查询的传,比如search_fields = ['=id', 'name']
		# 他就会拼接出['id__iexact', 'name__icontains']这两个list
		# 这里[]里面的写法叫做:列表生成式(有点像lambda)
		# [x*x for x in range(2,8)]   原型:[2*2,3*3,4*4,5*5,6*6,7*7]
		# 打印结果:[4, 9, 16, 25, 36, 49]
        orm_lookups = [
            self.construct_search(str(search_field))
            for search_field in search_fields
        ]

        base = queryset
        conditions = []
        for search_term in search_terms:
            queries = [
            	# Q查询——对对象的复杂查询
            	# 目前我的理解是这样,我们常用的id_contians只能对对象进行一次简单的过滤
            	# 运用Q可以运用 | & 等连接符设定复杂的过滤条件
            	# 比如Q(question__startswith='Who') | Q(question__startswith='What')
            	# 等价于 WHERE question LIKE 'Who%' OR question LIKE 'What%'
            	# 参考http://www.cnblogs.com/linjiqin/p/3817814.html
                models.Q(**{orm_lookup: search_term})
                for orm_lookup in orm_lookups
            ]
            # reduce() 函数会对参数序列中元素进行累积。
            # 这里就是把所有的queries用|连接起来
            # 在所有的列中搜索某个值
            conditions.append(reduce(operator.or_, queries))
        # 合并搜索条件
        queryset = queryset.filter(reduce(operator.and_, conditions))

        if self.must_call_distinct(queryset, search_fields):
            # Filtering against a many-to-many field requires us to
            # call queryset.distinct() in order to avoid duplicate items
            # in the resulting queryset.
            # We try to avoid this if possible, for performance reasons.
            # 当存在多对多的field的时候会调用distinct()去重,虽然我没看懂他的检查原理
            queryset = distinct(queryset, base)
        return queryset

其中这个代码很有意思,调用了一个getattr的函数,这是一个python的系统函数,可以获取某个对象的某个属性,比如getattr(view, 'search_fields', None)等价于调用view.search_fields。第三个参数就是当没有取到参数时候返回的默认值了。

    def get_search_fields(self, view, request):
        """
        Search fields are obtained from the view, but the request is always
        passed to this method. Sub-classes can override this method to
        dynamically change the search fields based on request content.
        """
        return getattr(view, 'search_fields', None)

自定义修改

class MySearchFilter(filters.SearchFilter):
    def filter_queryset(self, request, queryset, view):
        # 获取允许搜索配置信息
        search_fields = self.get_search_fields(view, request)

        # 检查request参数中有没有我们允许搜索的
        params_list = []
        for field in search_fields:
            # 去掉第一位的头
            param = request.query_params.get(field[1:] if self.lookup_prefixes.get(field[0]) else field, None)
            if param:
            # 如果匹配到信息就加进队列里面
                params_list.append(models.Q(**{self.construct_search(str(field)): param}))

        base = queryset
        # 用与操作合并所有条件
        queryset = queryset.filter(reduce(operator.and_, params_list))

        if self.must_call_distinct(queryset, search_fields):
            queryset = distinct(queryset, base)
        return queryset
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值