rest framework之过滤组件
一、普通过滤
(一)get_queryset
get_queryset方法是GenericAPIView提供的一个方法,旨在返回queryset数据集,而过滤就是要在这个方法返回数据集之前对数据进行筛选,然后返回筛选后的数据即可,那么也就是要求需要重写这个方法:
def get_queryset(self):
"""
Get the list of items for this view.
This must be an iterable, and may be a queryset.
Defaults to using `self.queryset`. This method should always be used rather than accessing `self.queryset`
directly, as `self.queryset` gets evaluated only once, and those results
are cached for all subsequent requests. You may want to override this if you need to provide different
querysets depending on the incoming request. (Eg. return a list of items that is specific to the user)
"""
assert self.queryset is not None, (
"'%s' should either include a `queryset` attribute, "
"or override the `get_queryset()` method."
% self.__class__.__name__
) queryset = self.queryset
if isinstance(queryset, QuerySet):
# Ensure queryset is re-evaluated on each request.
queryset = queryset.all()
return queryset
源码中的这个方法会从视图配置中获得queryset,然后判断是否属于QuerySet类型,如果属于,就会返回这个queryset。
(二)实例
- 请求API
class BookView(GenericViewSet):
serializer_class = BookModelSerializer
def get_queryset(self):
queryset = models.Book.objects.all()
title = self.request.query_params.get('title',None)
if title is not None:
queryset = models.Book.objects.filter(title=title).all()
return queryset
def list(self,request,*args,**kwargs):
queryset= self.get_queryset()
bs=self.get_serializer(queryset,many=True)
return Response(bs.data)
- 路由配置:
注意如果需要过滤,url中需要加入base_name属性,并且base_name的值就是过滤参数的名称:
router=routers.DefaultRouter()
router.register('books',views.BookView,base_name="title")
- 生成的路由:
^books/$ [name='title-list']
^books\.(?P<format>[a-z0-9]+)/?$ [name='title-list']
- 请求地址:
http://127.0.0.1:8020/books/?title=语文
二、django-filter过滤
(一)django-filter的简单使用
1、安装django-filter
pip install django-filter
2、注册django-filter
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'app01.apps.App01Config',
'rest_framework',
'django_filters', #注册django-filter
]
3、设置通用过滤后端
- 全局配置
REST_FRAMEWORK = {
'DEFAULT_FILTER_BACKENDS': ('django_filters.rest_framework.DjangoFilterBackend',)
}
- 局部视图设置
import django_filters.rest_framework
class BookView(GenericViewSet):
queryset = models.Book.objects.all()
serializer_class = BookModelSerializer
filter_backends = (django_filters.rest_framework.DjangoFilterBackend,)
4、指定筛选字段
如果需求都是些简单类型的筛选,那么可以在view或viewSet里面设置一个filter_fields属性,列出所有依靠筛选的字段集合。
import django_filters.rest_framework
from rest_framework.viewsets import ModelViewSet class BookView(ModelViewSet): ...
filter_fields = ('title',) #列出搜索字段
...
5、进行访问
- 路由配置
from rest_framework import routers
router=routers.DefaultRouter()
router.register('books',views.BookView) #无需base_name参数
urlpatterns = [
re_path('',include(router.urls)),
]
- 生成的路由
^books/$ [name='book-list']
^books\.(?P<format>[a-z0-9]+)/?$ [name='book-list']
^books/(?P<pk>[^/.]+)/$ [name='book-detail']
^books/(?P<pk>[^/.]+)\.(?P<format>[a-z0-9]+)/?$ [name='book-detail']
- 进行访问
http://127.0.0.1:8020/books/?title=语文
(二)FilterSet的简单使用
上面所搜索的字段是一对一的关系,没有涉及到外键以及多对多字段,如果有外键或者多对多关系,可以在filter_fields中使用‘__’进行跨越:
class BookView(ModelViewSet):
queryset = models.Book.objects.all()
serializer_class = BookModelSerializer
filter_backends = (django_filters.rest_framework.DjangoFilterBackend,)
# 列出搜索字段,其中publish__name为ForeignKey字段,authors__name为ManyToMany字段
filter_fields = ('title','publish__name','authors__name')
class Book(models.Model):
title=models.CharField(max_length=32)
price=models.IntegerField()
pub_date=models.DateField(null=True,blank=True)
publish=models.ForeignKey("Publish",on_delete=models.CASCADE)
authors=models.ManyToManyField("Author")
def __str__(self):
return self.title
models
此时请求地址:
#含外键
http://127.0.0.1:8020/books/?title=语文&publish__name=北京出版社 #含多对多
http://127.0.0.1:8020/books/?title=语文&publish__name=北京出版社&authors__name=张三
但这样外键和多对多将Django的双下划线约定作为API的一部分暴露出来。如果想显式地命名过滤器参数,可以显式地将它包含在FilterSet类中:
1、定义FilterSet类
import django_filters
from app01 import models class BookFilter(django_filters.rest_framework.FilterSet):
publish = django_filters.CharFilter(field_name="publish__name")
authors = django_filters.CharFilter(field_name="authors__name")
class Meta:
model = models.Book
fields = ['title', 'publish', 'authors']
2、在视图中使用定义的FilterSet类
class BookView(ModelViewSet):
queryset = models.Book.objects.all()
serializer_class = BookModelSerializer
filter_backends = (django_filters.rest_framework.DjangoFilterBackend,)
filter_class = BookFilter #使用定义的FilterSet类
此时请求地址:
http://127.0.0.1:8020/books/?title=语文&publish=北京出版社&authors=张三
3、总结
FilterSet可以实现较为复杂的过滤功能,如果是普通字段可以使用filter_fields 添加字段进行过滤,如果有外键、多对多以及范围(日期范围、价格范围)使用FilterSet.
三、其它过滤
(一)搜索过滤(SearchFilter)
支持基于简单查询参数的搜索,并且基于Django admin的搜索功能。
- 设置过滤后端
from rest_framework import filters class BookView(ModelViewSet): ...
filter_backends = (filters.SearchFilter,)
...
- 设置查询字段
from rest_framework import filters
class BookView(ModelViewSet):
queryset = models.Book.objects.all()
serializer_class = BookModelSerializer
# filter_backends = (django_filters.rest_framework.DjangoFilterBackend,)
filter_backends = (filters.SearchFilter,)
#凡是以下字段内容都会被搜到
search_fields = ('title','publish__name','authors__name')
当然可以通过在search_fields 前面添加各种字符来限制搜索行为:
'^' 以指定内容开始. '=' 完全匹配 '@' 全文搜索(目前只支持Django的MySQL后端) '$' 正则搜索
例如:
search_fields = ('=title',)
- 客户端访问
#将北京出版社的内容全部搜索出来
http://127.0.0.1:8020/books/?search=北京出版社
#将张三相关内容搜索出来
http://127.0.0.1:8020/books/?search=张三
通过关键词search进行搜索,可以搜索后端search_fields提供字段的内容。
SearchFilters类的默认搜索关键字为search,可以通过SEARCH_PARAM进行覆盖设置
class BookView(ModelViewSet):
...
SEARCH_PARAM = 'ss'
...
(二)排序筛选(OrderingFilter)
- 设置排序筛选后端
from rest_framework import filters class BookView(ModelViewSet): ...
filter_backends = (filters.OrderingFilter,)
...
- 指定支持排序的字段(ordering_fields )
from rest_framework import filters class BookView(ModelViewSet):
...
filter_backends = (OrderingFilter,)
ordering_fields = ('title', 'id') #指定支持排序的字段
...
- 客户端访问
通过关键字ordering请求返回的数据按照什么排序
#按照title排序
http://127.0.0.1:8020/books/?ordering=title #按照id排序
http://127.0.0.1:8020/books/?ordering=id
#按照id逆序
http://127.0.0.1:8020/books/?ordering=-id #按照多个字段排序
http://127.0.0.1:8020/books/?ordering=id,title
- 默认排序
如果需要在返回的数据中已经排好序了,可以在视图中使用ordering参数:
from rest_framework import filters
class BookView(ModelViewSet):
queryset = models.Book.objects.all()
serializer_class = BookModelSerializer
filter_backends = (filters.OrderingFilter,)
ordering_fields = ('title', 'id')
ordering=('-id',) #默认排序
客户端访问:
http://127.0.0.1:8020/books/
返回的是已经按照id逆序排列的数据。
参考文档:https://q1mi.github.io/Django-REST-framework-documentation/api-guide/filtering_zh/#filtering
rest framework之过滤组件的更多相关文章
- DRF框架(八)——drf-jwt手动签发与校验、搜索过滤组件、排序过滤组件、基础分页组件
自定义drf-jwt手动签发和校验 签发token源码入口 前提:给一个局部禁用了所有 认证与权限 的视图类发送用户信息得到token,其实就是登录接口,不然进不了登录页面 获取提交的username ...
- REST framework之分页组件
REST framework之分页组件 一 简单分页 查看第n页,每页显示n条 from rest_framework.pagination import PageNumberPagination # ...
- drf框架 - 过滤组件 | 分页组件 | 过滤器插件
drf框架 接口过滤条件 群查接口各种筛选组件数据准备 models.py class Car(models.Model): name = models.CharField(max_length=16 ...
- DRF内置过滤组件与排序组件结合使用
DRF内置过滤组件Filtering DRF提供了内置过滤组件Filtering,可以结合url路径的改变获取想要的数据,当然用户不可能在url访问路径中自己设置过滤条件,肯定是后端开发人员将前端页面 ...
- rest framework之路由组件
一.路由组件的使用 1.使用实例 在视图中继承GenericViewSet类来完成功能时,需要自己对路由的写法有所改变,需要在as_view中传入actions字典参数: re_path('books ...
- restful framework之序列化组件
一.Django自带序列化组件 from django.core import serializers def test(request): book_list = Book.objects.all( ...
- restful framework之权限组件
一.权限简介 只用超级用户才能访问指定的数据,普通用户不能访问,所以就要有权限组件对其限制 二.局部使用 from rest_framework.permissions import BasePerm ...
- restful framework之认证组件
一.认证介绍 只有认证通过的用户才能访问指定的url地址,比如:查询课程信息,需要登录之后才能查看,没有登录,就不能查看,这时候需要用到认证组件 二.局部使用 (1)models层: class Us ...
- RESTful源码笔记之RESTful Framework的基本组件
快速实例 Quickstart 序列化 创建一个序列化类 简单使用 开发我们的Web API的第一件事是为我们的Web API提供一种将代码片段实例序列化和反序列化为诸如json之类的表示形式的方式. ...
随机推荐
- 图形设计 X11
显示适配器驱动程序安装范例 AMD驱动加载 Intel驱动加载
- go语言从例子开始之Example16.函数递归
Go 支持 递归.这里是一个经典的阶乘示例. Example: package main import "fmt" func fact(n int) int{ //先设置退出条件 ...
- Java集合体系结构(List、Set、Collection、Map的区别和联系)
Java集合体系结构(List.Set.Collection.Map的区别和联系) 1.Collection 接口存储一组不唯一,无序的对象 2.List 接口存储一组不唯一,有序(插入顺序)的对象 ...
- 0xC0000005: 写入位置 0x00000000 时发生访问冲突的解决办法(转)
上面的意识就是你吧值付给了不该赋给的变量,或者说你把值付给了不能付给的变量(或者常量) ()最简单也最直接的错误可能就是scanf()的问题,我们都知道输入的时候都是scanf("%格式&q ...
- python中二维数组的建立,输入和输出
''' for循环: for i in range(x,y,dir): pass 首先这个区间是左闭右开 其次dir在省略的情况下默认为1,就是每次加一,也可以指定 python的数组: python ...
- css强制换行和超出部分隐藏实现
一.强制换行 1 word-break: break-all; 只对英文起作用,以字母作为换行依据. 2 word-wrap: break-word; 只对英文起作用,以单词作为换行依据. 3 whi ...
- chroot()使用
好多的程序,都有使用chroot来是程序chroot到一个目录下面,来保护文件系统,今天在看snort代码的时候,看到了实现,就贴出一个测试程序来,实际上是比较简单的. chroot()在lin ...
- hdu1574 I Hate It (线段树,查询区间最大值)
Description 很多学校流行一种比较的习惯.老师们很喜欢询问,从某某到某某当中,分数最高的是多少. 这让很多学生很反感. 不管你喜不喜欢,现在需要你做的是,就是按照老师的要求,写一个程序,模拟 ...
- nginx查看变量值
nginx查看变量值 location / { echo $host; #域名 echo $remote_addr; echo $remote_user; echo $time_local; echo ...
- [六省联考2017]分手是祝愿 题解(期望dp)
题目描述 B 君在玩一个游戏,这个游戏由 n 个灯和 n 个开关组成,给定这 n 个灯的初始状态,下标为从 1 到 n 的正整数. 每个灯有两个状态亮和灭,我们用 1 来表示这个灯是亮的,用 0 表示 ...