目录
1、2、1 视图配置和应用(filterset_fields)
猜想:filterset_fields里面的字段必须是数据库里面存在的字段
1、2、2 视图配置和应用(filterset_class)
1、条件搜索(GenericAPIView)
如果某个API需要传递一些条件进行搜索,其实就在是URL后面通过GET传参即可,例如:
/api/users?age=19&category=12
在drf中也有相应组件可以支持条件搜索。
1.1 自定义Filter
#views
from rest_framework.filters import BaseFilterBackend
class Filter1(BaseFilterBackend):
def filter_queryset(self, request, queryset, view):
age = request.query_params.get('age')
if not age:
return queryset
return queryset.filter(age=age)
class Filter2(BaseFilterBackend):
def filter_queryset(self, request, queryset, view):
user_id = request.query_params.get('id')
if not user_id:
return queryset
return queryset.filter(id__gt=user_id)
class UserView(ModelViewSet):
filter_backends = [Filter1, Filter2]
#queryset=queryset.filter(id=user.id,age=age)
#在执行出create方法外,用到self.filter_queryset时
#GenericAPIView类中
def filter_queryset(self, queryset):
#将你自定义的条件加入到quetyset.filter()中
for backend in list(self.filter_backends):
queryset = backend().filter_queryset(self.request, queryset, self)
return queryset
1.2第三方Filter
在drf开发中有一个常用的第三方过滤器:DjangoFilterBackend。
pip install django-filter
注册app:
INSTALLED_APPS = [
...
'django_filters',
...
]
两种方式(filterset_fields,filterset_class)
1、2、1 视图配置和应用(filterset_fields)
# views.py
from django_filters.rest_framework import DjangoFilterBackend
from app01 import models
class UserView(ModelViewSet):
filter_backends = [DjangoFilterBackend, ]
filterset_fields = ["id", "age", "email"]
queryset = models.UserInfo.objects.all()
#可以接受id,age,email字段
猜想:filterset_fields里面的字段必须是数据库里面存在的字段
1、2、2 视图配置和应用(filterset_class)
from django_filters.rest_framework import DjangoFilterBackend
from django_filters import FilterSet, filters
from app01 import models
class MyFilterSet(FilterSet):
depart = filters.CharFilter(field_name="depart__title", lookup_expr="exact")
min_id = filters.NumberFilter(field_name='id', lookup_expr='gte')
class Meta:
model = models.UserInfo
fields = ["min_id", "depart","age"]
#fields也可以接收model数据表所有的字段,默认等于
class UserView(ModelViewSet):
filter_backends = [DjangoFilterBackend, ]
filterset_class = MyFilterSet
queryset = models.UserInfo.objects.all()
自定义的filter类中:fields也可以接收model数据表所有的字段,默认条件等于
例如:传入age=10的,就默认queryser.filter(age=10)
1、2、3 更多条件(lookup_expr
)
from django_filters.rest_framework import DjangoFilterBackend
from django_filters import FilterSet, filters
class 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]
注意:可以自定义条件,实现limit功能
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'),
1、2、4全局配置和应用
# settings.py 全局配置
REST_FRAMEWORK = {
'DEFAULT_FILTER_BACKENDS': ['django_filters.rest_framework.DjangoFilterBackend',]
}
1、3 内置Filter
drf源码中内置了2个filter,分别是:
1、OrderingFilter,支持排序。
from rest_framework.filters import OrderingFilter
class UserView(ModelViewSet):
filter_backends = [OrderingFilter, ]
# ?order=id
# ?order=-id
# ?order=age
ordering_fields = ["id", "age"]
#必须是关联数据表中的字段
queryset = models.UserInfo.objects.all()
serializer_class = UserModelSerializer
注意:ordering_fields中的字段必须在数据表中(queryset相关连的数据表)存在,
参数必须是
order=id,升序,
order=-id降序
2、SearchFilter,(支持模糊搜索)。
from app01 import models
from rest_framework.filters import SearchFilter
class UserView(ModelViewSet):
# ?search=武沛%齐
filter_backends = [SearchFilter, ]
search_fields = ["id", "username", "age"]
queryset = models.UserInfo.objects.all()
注意:search_fields中的字段必须在数据表中(queryset相关连的数据表)存在,
参数必须是
search=laoji
"app01_userinfo"."id" LIKE %武沛齐% ESCAPE '\'
OR
"app01_userinfo"."username" LIKE %武沛齐% ESCAPE '\'
OR
"app01_userinfo"."age" LIKE %武沛齐% ESCAPE '\'
2、分页(GenericAPIView)
在查看数据列表的API中,如果 数据量 比较大,肯定不能把所有的数据都展示给用户,而需要通过分页展示。
在drf中为我们提供了一些分页先关类:
BasePagination,分页基类
PageNumberPagination(BasePagination) 支持 /accounts/?page=4&page_size=100 格式的分页
LimitOffsetPagination(BasePagination) 支持 ?offset=100&limit=10 格式的分页
CursorPagination(BasePagination) 支持 上一下 & 下一页 格式的分页(不常用)
2、1APIView视图
如果编写视图是直接继承APIView,那么在使用分页时,就必须自己手动 实例化 和 调用相关方法。
2、1、1PageNumberPagination
2、1、2LimitOffsetPagination
2、1、3CursorPagination
2、2GenericAPIView派生类
如果是使用 ListModelMixin
或 ModelViewSet
,则只需要配置相关类即可,内部会自动执行相关分页的方法。
2、2、1PageNumberPagination
from rest_framework.pagination import PageNumberPagination
class MyPage(LimitOffsetPagination):
page_size = 2 #每页多少条
page_size_query_param = "size" #page_size设置新的变量名
class UserView2(ModelViewSet):
pagination_class = MyPage
2、2、2LimitOffsetPagination
from rest_framework.pagination import LimitOffsetPagination
class MyPage(LimitOffsetPagination):
default_limit= 10
max_limit = 100
offset_query_param = None
class UserView2(ModelViewSet):
pagination_class = MyPage
2、2、3CursorPagination
2、3全局配置
#setting.py
REST_FRAMEWORK = {
# # 分页配置
"DEFAULT_PAGINATION_CLASS": "xxx.xx.xx"
}