DRF的filter组件 环球消息

2023-04-23 12:50:03 来源:博客园 分享到:
DRF的Filter组件

如果某个API需要传递一些条件进行搜索,其实就在是URL后面通过GET传参即可,例如:

/api/users?age=19&category=12

在drf中filter组件可以支持条件搜索。


(资料图)

1. 自定义filter
# models.pyfrom django.db import modelsclass Role(models.Model):    """ 角色表 """    title = models.CharField(verbose_name="名称", max_length=32)class Department(models.Model):    """ 部门表 """    title = models.CharField(verbose_name="名称", max_length=32)class UserInfo(models.Model):    username = models.CharField(verbose_name="用户名", max_length=32)    age = models.CharField(verbose_name="年龄", max_length=32)    level_choice = ((1, "VIP"), (2, "SVIP"), (3, "PARTNER"))    level = models.SmallIntegerField(verbose_name="级别", choices=level_choice)    email = models.CharField(verbose_name="邮箱", max_length=32)    # 创建外键    depart = models.ForeignKey(verbose_name="部门", to="Department", on_delete=models.CASCADE)    # 多对多    roles = models.ManyToManyField(verbose_name="角色", to="Role")
# views.pyfrom rest_framework import serializersfrom rest_framework.filters import BaseFilterBackendfrom rest_framework.viewsets import ModelViewSetfrom api import models# Create your views here.class UserSerializer(serializers.ModelSerializer):    level_text = serializers.CharField(source="get_level_display", read_only=True)    extra = serializers.SerializerMethodField(read_only=True)    class Meta:        model = models.UserInfo        fields = ["username", "age", "email", "level_text", "extra"]    def get_extra(self, obj):        return "我是多余的"# 自定义Filterclass Filter1(BaseFilterBackend):    def filter_queryset(self, request, queryset, view):        age = request.GET.get("age")  # 可以使用request.query_params        if not age:            return queryset        return queryset.filter(age=age)class Filter2(BaseFilterBackend):    def filter_queryset(self, request, queryset, view):        id = request.query_params.get("id")        if not id:            return queryset        return queryset.filter(id=id)class UserView(ModelViewSet):    filter_backends = [Filter1, Filter2]  # 加入需要传递的Filter    queryset = models.UserInfo.objects.all()  # GenericAPIView这个类提供的变量    serializer_class = UserSerializer

返回值:

源码流程2. 第三方filter(常用)

在drf开发中有一个常用的第三方过滤器:DjangoFilterBackend。

pip install django-filter

注册app:

INSTALLED_APPS = [    ...    "django_filters",    ...]
示例1: 简单

视图配置和应用:

# views.pyfrom rest_framework import serializersfrom rest_framework.viewsets import ModelViewSetfrom django_filters.rest_framework import DjangoFilterBackendfrom app01 import modelsclass UserModelSerializer(serializers.ModelSerializer):    level_text = serializers.CharField(        source="get_level_display",        read_only=True    )    extra = serializers.SerializerMethodField(read_only=True)    class Meta:        model = models.UserInfo        fields = ["username", "age", "email", "level_text", "extra"]    def get_extra(self, obj):        return 666class UserView(ModelViewSet):    filter_backends = [DjangoFilterBackend, ]    filterset_fields = ["id", "age", "email"]    queryset = models.UserInfo.objects.all()    serializer_class = UserModelSerializer    def perform_create(self, serializer):        """ 序列化:对请求的数据校验成功后,执行保存。"""        serializer.save(depart_id=1, password="123")
示例2: 复杂

视图配置和应用(示例3):

from rest_framework import serializersfrom rest_framework.viewsets import ModelViewSetfrom django_filters.rest_framework import DjangoFilterBackend, OrderingFilterfrom django_filters import FilterSet, filtersfrom app01 import modelsclass UserModelSerializer(serializers.ModelSerializer):    level_text = serializers.CharField(        source="get_level_display",        read_only=True    )    depart_title = serializers.CharField(        source="depart.title",        read_only=True    )    extra = serializers.SerializerMethodField(read_only=True)    class Meta:        model = models.UserInfo        fields = ["id", "username", "age", "email", "level_text", "extra", "depart_title"]    def get_extra(self, obj):        return 666class MyFilterSet(FilterSet):    # /api/users/?min_id=2  -> id>=2    min_id = filters.NumberFilter(field_name="id", lookup_expr="gte")    # /api/users/?name=wupeiqi  -> not ( username=wupeiqi )    name = filters.CharFilter(field_name="username", lookup_expr="exact", exclude=True)    # /api/users/?depart=xx     -> depart__title like %xx%    depart = filters.CharFilter(field_name="depart__title", lookup_expr="contains")    # /api/users/?token=true      -> "token" IS NULL    # /api/users/?token=false     -> "token" IS NOT NULL    token = filters.BooleanFilter(field_name="token", lookup_expr="isnull")    # /api/users/?email=xx     -> email like xx%    email = filters.CharFilter(field_name="email", lookup_expr="startswith")    # /api/users/?level=2&level=1   -> "level" = 1 OR "level" = 2(必须的是存在的数据,否则报错-->内部有校验机制)    # level = filters.AllValuesMultipleFilter(field_name="level", lookup_expr="exact")    level = filters.MultipleChoiceFilter(field_name="level", lookup_expr="exact", choices=models.UserInfo.level_choices)    # /api/users/?age=18,20     -> age in [18,20]    age = filters.BaseInFilter(field_name="age", lookup_expr="in")    # /api/users/?range_id_max=10&range_id_min=1    -> id BETWEEN 1 AND 10    range_id = filters.NumericRangeFilter(field_name="id", lookup_expr="range")    # /api/users/?ordering=id     -> order by id asc    # /api/users/?ordering=-id     -> order by id desc    # /api/users/?ordering=age     -> order by age asc    # /api/users/?ordering=-age     -> order by age desc    ordering = filters.OrderingFilter(fields=["id", "age"])    # /api/users/?size=1     -> limit 1(自定义搜索)    size = filters.CharFilter(method="filter_size", distinct=False, required=False)        class Meta:        model = models.UserInfo        fields = ["id", "min_id", "name", "depart", "email", "level", "age", "range_id", "size", "ordering"]    def filter_size(self, queryset, name, value):        int_value = int(value)        return queryset[0:int_value]class UserView(ModelViewSet):    filter_backends = [DjangoFilterBackend, ]    filterset_class = MyFilterSet    queryset = models.UserInfo.objects.all()    serializer_class = UserModelSerializer    def perform_create(self, serializer):        """ 序列化:对请求的数据校验成功后,执行保存。"""        serializer.save(depart_id=1, password="123")
补充

lookup_expr有很多常见选择:

"exact": _(""),"iexact": _(""),"contains": _("contains"),"icontains": _("contains"),"startswith": _("starts with"),"istartswith": _("starts with"),"endswith": _("ends with"),  "iendswith": _("ends with"),    "gt": _("is greater than"),"gte": _("is greater than or equal to"),"lt": _("is less than"),"lte": _("is less than or equal to"),"in": _("is in"),"range": _("is in range"),"isnull": _(""),    "regex": _("matches regex"),"iregex": _("matches regex"),

全局配置和应用:

# settings.py 全局配置REST_FRAMEWORK = {    "DEFAULT_FILTER_BACKENDS": ["django_filters.rest_framework.DjangoFilterBackend",]}
3. 内置filter

drf源码中内置了2个filter,分别是:

OrderingFilter,支持排序。

from rest_framework import serializersfrom rest_framework.viewsets import ModelViewSetfrom app01 import modelsfrom rest_framework.filters import OrderingFilterclass UserModelSerializer(serializers.ModelSerializer):    level_text = serializers.CharField(        source="get_level_display",        read_only=True    )    depart_title = serializers.CharField(        source="depart.title",        read_only=True    )    extra = serializers.SerializerMethodField(read_only=True)    class Meta:        model = models.UserInfo        fields = ["id", "username", "age", "email", "level_text", "extra", "depart_title"]    def get_extra(self, obj):        return 666class UserView(ModelViewSet):    filter_backends = [OrderingFilter, ]    # ?order=id    # ?order=-id    # ?order=age    ordering_fields = ["id", "age"]    queryset = models.UserInfo.objects.all()    serializer_class = UserModelSerializer    def perform_create(self, serializer):        """ 序列化:对请求的数据校验成功后,执行保存。"""        serializer.save(depart_id=1, password="123")

SearchFilter,支持模糊搜索。

from rest_framework import serializersfrom rest_framework.viewsets import ModelViewSetfrom app01 import modelsfrom rest_framework.filters import SearchFilterclass UserModelSerializer(serializers.ModelSerializer):    level_text = serializers.CharField(        source="get_level_display",        read_only=True    )    depart_title = serializers.CharField(        source="depart.title",        read_only=True    )    extra = serializers.SerializerMethodField(read_only=True)    class Meta:        model = models.UserInfo        fields = ["id", "username", "age", "email", "level_text", "extra", "depart_title"]    def get_extra(self, obj):        return 666class UserView(ModelViewSet):    filter_backends = [SearchFilter, ]    search_fields = ["id", "username", "age"]    queryset = models.UserInfo.objects.all()    serializer_class = UserModelSerializer    def perform_create(self, serializer):        """ 序列化:对请求的数据校验成功后,执行保存。"""        serializer.save(depart_id=1, password="123")
"app01_userinfo"."id" LIKE %18% ESCAPE "\" OR "app01_userinfo"."username" LIKE %18% ESCAPE "\" OR "app01_userinfo"."age" LIKE %18% ESCAPE "\"
标签:

DRF的filter组件 环球消息

来源:博客园 2023-04-23 12:50:03

洋甘菊纯露的功效与作用对皮肤的作用_洋甘菊纯露的功效与作用 当前热闻

来源:互联网 2023-04-23 12:28:04

焦点热议:《青春之城》:用励志之歌,点燃年轻人心中的奋斗之火

来源:影视独舌 2023-04-23 12:11:52

招标询价公告

来源:全球赣商网 2023-04-23 11:36:47

阿拉善英雄会梦想破灭,顾地科技4元出售梦汽文旅 天天热资讯

来源:支点财经 2023-04-23 11:04:17

义乌那家医院男科专业比较好『排名』义乌较好男科医院在那里

来源:中华网健康 2023-04-23 11:15:31

一季度我国固定资产投资107282亿元 同比增长5.1%

来源:中国青年报客户端 2023-04-23 10:48:51

当前时讯:是卧底吧?小莫里斯13投3中&三分仅8中1拿9分 正负值-19全场最低

来源:天下足球最新帖子 2023-04-23 10:19:29

天天热点!福州仓山山姆会员商店开业在即,一站式超级购物体验重磅来袭

来源:综合 2023-04-23 10:24:19

中国科大赵瑾获“中国青年女科学家奖”

来源:大皖新闻 2023-04-23 09:36:02

雨雾流云似瀑连!安徽天柱山金色云瀑震撼壮美

来源:BRTV都市晚高峰 2023-04-23 09:04:39

ps怎么把图片变成手绘线稿(ps怎么把图片变成手绘) 世界快资讯

来源:互联网 2023-04-23 09:02:57

每日聚焦:qq登录微信和手机号登录有什么区别_qq登录微信

来源:互联网 2023-04-23 08:24:39

苹果钱包怎么用nfc-苹果钱包怎么用_世界新资讯

来源:互联网 2023-04-23 07:39:16

继承之战第一季_关于继承之战第一季介绍 今日讯

来源:互联网 2023-04-23 07:20:49

新动态:同心逐梦展风采 激扬青春创未来

来源:百姓生活官方号 2023-04-23 07:02:55

欧洲肉鸽

来源:互联网 2023-04-23 06:28:18

今日讯!武磊当选官方MVP!绝杀球帅炸:10秒狂奔全场,超车多人后进单刀

来源:我爱英超 2023-04-23 05:37:29

马斯克:预计未来1到2个月内进行SpaceX“星舰”的再次发射尝试|热门

来源:IT之家 2023-04-23 05:04:30

世界焦点!360直播导航下载安装到手机_360直播导航

来源:互联网 2023-04-23 04:34:16

天啊 全智贤孙锡久有望合作新剧,你希望全智贤出演吗?|世界今亮点

来源:哔哩哔哩 2023-04-23 03:37:11

孔燕-全球实时

来源:互联网 2023-04-23 03:03:25

环球快消息!食品科学与工程专业前景如何 食品科学与工程专业就业前景怎么样

来源:城市网 2023-04-23 03:01:06

cad形位公差怎么标注_cad形位公差如何标注

来源:互联网 2023-04-23 01:33:03

当前报道:主销车型63万元 高合HiPhi Z交付量超1,000台

来源:搜狐科技 2023-04-23 01:09:52

市州观察丨遂宁打响春灌用水“保卫战” 天天时快讯

来源:四川在线 2023-04-23 01:05:30

安定片购买平台_安定片药店有卖吗|环球通讯

来源:互联网 2023-04-22 23:40:42

关注:西藏cpa什么时候报名

来源:会计网 2023-04-22 23:08:04

[担保]金能科技(603113):金能科技股份有限公司关于2023年度公司及全资子公司之间担保额度

来源:中财网 2023-04-22 22:46:33

每日看点!空军师长开着70吨轰炸机,紧贴美航母甲板飞行,想再秀一次惨了

来源:洞察军事 2023-04-22 22:04:01

Copyright   2015-2022 全球知识产权网 版权所有  备案号:豫ICP备20009784号-11   联系邮箱:85 18 07 48 3@qq.com