46.drf过滤、搜索、排序

时间:2022-11-09 16:11:51

DRF的过滤类

drf过滤器在filters模块中,主要有四个类
  1. BaseFilterBackend:过滤基类,留好占位方法待后续继承
  2. SearchFilter:继承BaseFilterBackend
  3. OrderingFilter:继承BaseFilterBackend
  4. DjangoObjectPermissionsFilter:继承BaseFilterBackend,3.9版本之后废除
 

过滤的使用

DRF通用列表视图的默认行为是返回一个模型的全部queryset
比如说模型存储了1W条数据,默认会将1W条全部取出,如果不想一次性取出,只需要其中的一部分,需要对查询的结果进行过滤
如果继承了GenericAPIView及以上的视图类,有派生出的 get_queryset方法只需在视图中重写.get_queryset()方法
示例1-根据模型字段进行过滤
# 继承的ModelViewSet
class GetInfoLIst(ModelViewSet):
    queryset = UserInfo.objects.all()
    serializer_class = UserSerializer
    # 重写过滤方法
    def get_queryset(self):
        # 获取当前用户username
        username = self.request.user.username
        # 过滤出与当前用户username一致的信息
        return UserInfo.objects.filter(username=username)
示例2-根据url路径进行过滤
#路由 
path('user/<str:username>/', UserList.as_view()),
 
# views
# url示例: 127.0.0.1:8000/user/username/
class UserList(ListAPIView):
    serializer_class = UserSerializer

    def get_queryset(self):
        # 获取请求路由中的username
        username = self.kwargs['username']
        return UserInfo.objects.filter(username=username)
示例3-根据url携带参数进行过滤
#url 示例:127.0.0.1:8000/user/?username=xxxx
# 继承的ModelViewSet
class GetInfoLIst(ModelViewSet):
    queryset = UserInfo.objects.all()
    serializer_class = UserSerializer
    # 重写过滤方法
    def get_queryset(self):
        #从url参数中获取username,如果没有则是None
        # query_params.get是从url获取参数的方法
        username = self.request.query_params.get('username',None)
       if username is None:
           return UserInfo.object.all()
       else:
        return UserInfo.objects.filter(username=username)
 

DRF三种过滤的工具

DjangoFilterBackend
#安装
pip3.9 install django-filter

#注册
INSTALLED_APPS = [
    'django_filters',
]
过滤配置-全局
与权限配置一样,过滤也分全局过滤配置和局部过滤配置
REST_FRAMEWORK = {
    # 全局过滤配置
    'DEFAULT_FILTER_BACKENDS':
        # 值是元组,将django_filters配置上,进行全局性的过滤
        ('django_filters.rest_framework.DjangoFilterBackend',)
        
    
}
过滤配置-局部
from django_filters.rest_framework import DjangoFilterBackend #导包
class UserList(ListAPIView):
    # 视图级别过滤
    filter_backends = (DjangoFilterBackend,)# 指定后端
字段过滤
from django_filters.rest_framework import DjangoFilterBackend #导包
class UserList(ListAPIView):

    filter_backends = (DjangoFilterBackend,) # 指定后端
    filterset_fields = ('username','id') #要过滤的字段
    
'''
将为指定的字段自动创建一个 FilterSet 类
可以发送类似请求: http://xxxx/api/xxx?username=xxxx&id=xxxx
Django-filter模块的默认模式是完全匹配模式,需要自定义匹配模式参考https://django-filter.readthedocs.io/en/latest/index.html
'''
 
SearchFilter搜索过滤
SearchFilter 类是DRF自带的过滤器,支持基于简单的单个查询参数的搜索,并且基于Django admin的搜索功能
from rest_framework import filters


class UserList(ListAPIView):
    filter_backends = (DjangoFilterBackend,filters.SearchFilter)  # 指定后端
    # 视图中设置了 search_fields 属性时,才会应用 SearchFilter 类
    # search_fields只支持文本类型字段,例如 CharField 或 TextField
    search_fields = ('username',)
    
'''
在url中默认的搜索参数是search
url示例 - http://xxxx/api/users?search=木子
会过滤出username=木子的信息
'''
修改url中的搜索参数
# 上述默认以及search字段进行搜索,如果想要修改默认的search字段
REST_FRAMEWORK = {
    # 全局过滤配置
    'DEFAULT_FILTER_BACKENDS':
        # 值是元组,将django_filters配置上,进行全局性的过滤
        ('django_filters.rest_framework.DjangoFilterBackend',)
    # 修改search_fields链接搜索时的字段
    "SEARCH_PARAM":"find"
    
}
""" 
url示例 - http://xxxx/api/users?find=木子

"""
匹配模式
默认情况下,搜索不区分大小写,并使用部分匹配的模式
可以同时有多个搜索参数,用空格和/或逗号分隔
如果使用多个搜索参数,则仅当所有提供的模式都匹配时才在列表中返回对象
可以通过在 search_fields 前面添加各种字符来限制搜索行为
  1. ^ 以指定内容开始
  2. = 完全匹配
  3. @ 全文搜索(目前只支持Django的MySQL后端)
  4. $ 正则搜索
search_fields = ('=username') # 用户名必须完全一致,不能局部一致
OrderingFilter排序
OrderingFilter 类支持简单的查询参数,以控制查询集的元素顺序
class UserList(ListAPIView):
    filter_backends = (filters.OrderingFilter)  # 指定后端
    ordering_filter = ('username',) # 指定可以排序的字段
    ordering_fields = '__all__' # 所有字段,和指定二选一
    
'''
url中的查询参数默认ordering
http://xxxx/api/user?ordering=username
和search一样,如果要修改默认的查询参数,可以通过 ORDERING_PARAM指定
'''
#排序
http://xxxx/api/user?ordering=username # 默认排序
http://xxxx/api/user?ordering=-username #反向排序
http://xxxx/api/user?ordering=username,age  #多个字段进行排序

指定默认的排序方式

class UserList(ListAPIView):
    filter_backends = (filters.OrderingFilter)  # 指定后端
    ordering_filter = ('username',) # 指定可以排序的字段
    ordering = ('username') #默认初始用username排序

自定义过滤

  1. 自定义通用过滤后端,需要继承 BaseFilterBackend 类
  2. 重写filter_queryset(self, request, queryset, view) 方法
  3. 应返回一个新的过滤后的查询集
除了允许客户端执行搜索和过滤之外,自定义过滤器后端还可以限制当前请求或用户能够访问的对象
# 继承filters.BaseFilterBackend
class IsOwnerFilterBackend(filters.BaseFilterBackend):
    def filter_queryset(self, request, queryset, view):
        # 过滤与当前用户一致
        return queryset.filter(owner=request.user)
        
'''
在视图中,通过重写 get_queryset() 方法,也能实现上面的操作
编写自定义的过滤器后端,可以在不同的视图或所有的API上,方便的重用这一功能
'''
 
 

46.drf过滤、搜索、排序