程序员文章、书籍推荐和程序员创业信息与资源分享平台

网站首页 > 技术文章 正文

Python DRF 自定义后端过滤器

hfteth 2025-05-24 14:25:46 技术文章 3 ℃

用DRF做了一些接口,用到数据的过滤,每次很多fiter就挺烦人的,就琢磨了一个自定义的过滤类,交流一下,要是有高手看到就指点指点,还能怎么继续优化。

通常复杂查询,我习惯post提交,django有一个很好的django-filter库,就是自己使用的不是很习惯,而且django-filter是地址栏提交的,前端也不熟,调试不方便。

在rest_framework的filter已经提供了一个基类BaseFilterBackend,定义了filter_queryset的方法,所以继承BaseFilterBackend后重写这个方法就可以。

在ViewSet里面,我先预定义一个post_fields字典用于提交字段和搜索字段的转换:

class MyViewSets(MyModelViewSets):
    filter_backends = [SearchFilterBackend]
    my_post_fields = {'name': 'name', 'age':'age__range', 'type':'type__name'}
    # 可以直接用 “__” 关联外键。如果需要扩大搜索范围,直接修改my_post_fields的内容就可以。
    # 因为是字典定义,前后端提交字段名称完全可以和后端脱离。

过滤器类,主要使用Q对象来实现过滤,Q的默认关系OR,需要指定为AND,Q的条件只要在children的属性append进来就可以。

from rest_framework import filters
from django.db.models import Q

class SearchFilterBackend(filters.BaseFilterBackend):

    def get_search_fields(self, view, request):
	      # 获取自定义的搜索列表
  	    return getattr(view, 'my_post_fields', None)
		

    def filter_queryset(self, request, queryset, view):
        # 所有关键字是and关系,提交的字段不在预设范围的忽略,
        # 提交一个值就判断相同,提交list类型,就是判断包含其中。
        q_and = Q()
        q_and.connector = 'AND'
        for post_field, model_field in search_fields.items():
            if post_field in data and data[post_field] is not None and data[post_field] not in [[], '']:
                if type(data[post_field]) == list and not model_field.endswith('__range'):
                    search_type = '__in'
                else:
                    search_type = ''
                q_and.children.append((model_field + search_type, data[post_field]))
        queryset = queryset.filter(q_and)

        return queryset

自己用下来还觉得挺方便的,欢迎交流

Tags:

最近发表
标签列表