过滤
# 1. DRF过滤介绍
我们之前写的结构其实都没有进行过滤,比如说,我们根据id升序或者降序-id,发现结果都是一样的,我们一起用postman来测试看看。
postman升序测试:127.0.0.1:8000/api/game.json?ordering=id
postman测试降序:127.0.0.1:8000/api/game.json?ordering=-id
为啥呐,我的升序和降序都是一样的呐,后面我们在仔细看看,原来你用的数据源都是一样的,都是 queryset = Game.objects.all()。
# 2. 利用get_queryset过滤
query_set是我们的get_queryset方法提供的,我们只需要重写 get_queryset方法就可以了。如下:
from .custom_model_view_set import CustomModelViewSet
class GameView(CustomModelViewSet):
queryset = Game.objects.all()
serializer_class = GameSerializer
def get_queryset(self):
ordering = self.request.query_params.get('ordering') #获取参数
if not ordering:
queryset = Game.objects.all()
else:
queryset = Game.objects.all().order_by(ordering) #利用django降序
return queryset
2
3
4
5
6
7
8
9
10
11
12
好的,我们再来测试一下:127.0.0.1:8000/api/game.json?ordering=-id
# 3. django-filter过滤
django-filter库包括一个DjangoFilterBackend类,它支持REST框架的高度可定制的字段过滤。
# 3.1 安装
pip install django-filter
# 3.2 官网和github
https://django-filter.readthedocs.io/en/master/guide/rest_framework.html
https://github.com/carltongibson/django-filter
2
3
# 3.3 settings.py中注册
INSTALLED_APPS = [
""""""
'django_filters',
]
2
3
4
# 3.4 全局安装
说明:在settings.py中安装全局过滤器配置
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': (
..
),
....
#全局配置过滤器
'DEFAULT_FILTER_BACKENDS': (
'django_filters.rest_framework.DjangoFilterBackend',
....
),
}
2
3
4
5
6
7
8
9
10
11
# 3.5 局部安装
说明:局部安装,只需要作用于某个视图,我们为了测试,我们就用局部的吧。
from .custom_model_view_set import CustomModelViewSet
#局部安装使用
from rest_framework import filters
from django_filters.rest_framework import DjangoFilterBackend
class GameView(CustomModelViewSet):
queryset = Game.objects.all()
serializer_class = GameSerializer
#导入过滤器
filter_backends = (DjangoFilterBackend,)
#定义过滤字段,这个字段需要在模型类中存在
filter_fields = ('name', 'status')
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
postman运行结果:
单个搜索:127.0.0.1:8000/api/game.json?name=QQ 炫舞
组合搜索:127.0.0.1:8000/api/game.json?name=QQ 炫舞&status=0
# 4. 自定义过滤
不知道大家发现没有,上面的过滤只能是精确匹配,不能做到模糊匹配,那我们想要做到模糊匹配过滤,这个时候我们就要自定义 过滤了。跟之前还是一样需要自己新建一个 custom_filter.py,那我们的目录结构如下:
...
-app06
-migrations
...
-app.py
-models.py
-custom_filter.py #新建,自定义过滤
...
...
2
3
4
5
6
7
8
9
好啦,我们编辑 custom_filter.py,编写我们的自定义的过滤:(自定义过滤,支持模糊匹配)
from django_filters import rest_framework as filters
from .models import Game
class GameFilter(filters.FilterSet):
min_status = filters.NumberFilter(field_name='status', lookup_expr='gte')
max_status = filters.NumberFilter(field_name='status', lookup_expr='lte')
#根据名字过滤忽略大小写
name = filters.CharFilter(field_name='name', lookup_expr='icontains')
class Meta:
model = Game
fields = ('min_status', 'max_status') # 允许精准查询的字段
search_fields = ('name',) # 允许模糊查询的字段
2
3
4
5
6
7
8
9
10
11
12
13
14
具体使用方法,请查看官网:
https://django-filter.readthedocs.io/en/master/guide/rest_framework.html
这边我们就不带大家看了,我们继续,我们来修改视图:
from .custom_model_view_set import CustomModelViewSet
from django_filters.rest_framework import DjangoFilterBackend
from .custom_filter import GameFilter #导入自定义过滤
class GameView(CustomModelViewSet):
queryset = Game.objects.all()
serializer_class = GameSerializer
filter_backends = (DjangoFilterBackend,)
# filter_fields = ('name', 'status')
filterset_class = GameFilter #上面的就不需要了,用我们自定义的过滤
2
3
4
5
6
7
8
9
10
11
12
13
好哒,我们再来测试一把:
单个搜素条件:http://127.0.0.1:8000/api/game.json?name=QQ
组合搜索:http://127.0.0.1:8000/api/game.json?name=QQ&min_status=1
区间值搜索:http://127.0.0.1:8000/api/game.json?min_status=0&max_status=2