Django rest Framework入门 五 :认证、权限、限流、分页和过滤
写在前面
以下提到的代码的代码仓库:https://github.com/yexia553/drf
分支: others
认证和权限
在实际开发中,认证这一部分常常是使用jwt,但jwt是相对独立并且比较复杂的模块,这里就不过多记录,以后有机会专门写一下jwt和drf的配合使用。
认证部分的配置代码只要修改demo.settings就行了,具体如下:
1 | REST_FRAMEWORK = { |
其中AnonRateThrottle表示对未认证用户进行限流,是通过不同的IP来区分不同的用户的,UserRateThrottle是对认证用户进行限流,通过id来区分不同的用户。
这里设置为未认证用户每天100次请求次数,认证用户每分钟100次请求次数。
- 对视图进行限流
也可以通过ScopedRateThrottle对视图进行限流,以下是示例代码,代码仓库中并没有。
视图类代码:
1 | class ContactDetailView(APIView): |
settings.rest_framework配置修改
1 | REST_FRAMEWORK = { |
排序
排序就是在对api进行请求的时候加上ordering参数,就可以在请求的返回结果中对某一个字段进行排序。
比如:
/books/bookinfos?ordering=title 就会在返回结果中针对title进行排序
在DRF的排序需要依赖于django-filter实现,所以要先安装:pip install django-filter
安装好之后要修改settings文件:
1 | INSTALLED_APPS = [ |
到这里就可以在API请求中对数据进行排序了,比如:
/books/bookinfos?ordering=title
过滤器
所谓过滤其实就是在API请求的时候加上一些参数,限制返回的结果,比如只查询id为1的书本信息,或者查询id大于2小于5的书本信息。
DRF上应用过滤器有两种方式,一种配置简单,但是功能也有限,适用于比较需要简单的场景,另一种代码较多,但是功能强大。
不论是那种方法,都需要依赖于django-filter,所以需要先安装:pip install django-filter
安装好之后还要修改settings:
1 | INSTALLED_APPS = [ |
- 简单应用
过滤器的简单应用其实非常简单,只要在视图类中添加上filter_fields属性指定可以用于过滤的字段就可以了,如下:
1 | class HeroInfoModelViewSet(ModelViewSet): |
上面的代码中指明了可以对id和name进行过滤,比如:GET /books/heroinfos?id=1
GET /books/heroinfos?name=袁隆平
虽然这种方法很简单就能实现过滤的功能,但是也如上面的两个例子展示的那样,只能实现很简单的过滤,在过滤的时候必须明确地指定需要过滤的参数和对应的值,没办法搜索一个范围,比如我想搜索id大于2小于5之间所有的英雄就只能一次查询id=3,id=4,不能一次性查询。
而且对于诸如时间这样的数据类型,这种简单的过滤器也只能按照字符串处理,而不能按照时间格式来处理。
- 高级应用
过滤器的高级应用需要配置多种数据类型的处理方式和自定义一个过滤器类。
- 在应用路径(book)下创建一个filters.py文件
filters.py里面主要包含两部分,一是各种数据类型的处理方式,比如布尔类型、字符串、时间等等,二是为视图类编写过滤器类,下面的代码中为BookInfoModelViewSet编写的过滤器类。
1 | from django_filters import rest_framework as filters |
- 在视图类中添加filter_class字段
1 | class BookInfoModelViewSet(ModelViewSet): |
到这里就可以使用过滤器了。
查询id大于10的书: GET /books/bookinfos/?id__gte=10
查询出版年份早于1986年的书: GET /books/bookinfos/?pub_date__year__lt=1986
查询书本名字以“天”开头的书: GET /books/bookinfos/?title__startswith=天
过滤器的高级使用基本就是这样
分页
分页其实就是把数据库中的数据分批返回给请求者,而不是一次性把所有的数据都返回给请求者,这样容易出问题,比如数据库中商品表有一千万条数据,总不能一次性把者一千万条数据都返回给请求者,这样服务器要多大的配置才能完成,而且客户端也没办法接收这么多数据。
应用分页有如下几个步骤:
- 创建自定义的分页处理器
文件位置如下:demo.utils.custom_pagination.py
1 | from rest_framework.pagination import PageNumberPagination as PNPG |
- 修改settings文件
1 | # rest framework settings |
- 使用
查询第二页内容:GET /books/bookinfos/?page=2
查询第二页,并且让每一页返回3条数据:GET /books/bookinfos/?page=2&page_size=3
异常处理
DRF还有一个功能就是可以捕捉异常,默认情况下可以捕捉的异常如下:
- APIException 所有异常的父类
- ParseError 解析错误
- AuthenticationFailed 认证失败
- NotAuthenticated 尚未认证
- PermissionDenied 权限决绝
- NotFound 未找到
- MethodNotAllowed 请求方式不支持
- NotAcceptable 要获取的数据格式不支持
- Throttled 超过限流次数
- ValidationError 校验失败
虽然能够捕捉的异常已经很多了,但是不可能捕捉所有的异常,这里以数据库异常为例。
首先要创建自定义异常处理函数:
1 | from rest_framework.views import exception_handler as drf_exception_handler |
这样就算可以了,如果想要验证的话,可以手动raise一个DatabaseError看看DRF能否捕捉到,这里没有准备案例。