【Django drf】认证类 权限类 频率类 过滤类 排序类 分页类
认证类
认证类的作用:
实现某些接口,登录之后能访问,有的接口不登录就能访问
前期准备
登录接口:
首先写一个登录接口,这个接口返回token,下一次请求浏览器只要带着token过来,就是说明用户登录了,不带token,就说明没有登录。
所以这个token可以放在请求的什么位置?
请求首行 or 请求头 or 请求体
- 对于post请求 ---> token可以放请求体
- 对于get 请求 ---> get请求没有请求体,token可以放在请求首行的地址栏
- 其实, 一般token放在请求头上传到后端。
前端传入的数据从哪里取?
- 对于post请求中携带的token:
原生django:request.body
request.POST
Django drf:request.data
- 对于get请求中携带的token:
原生django:request.get
Django drf:request.query_params
综上所述,在这个我们的示例下token暂时通过get请求的地址栏(请求首行)传到后端。
通过实现一个需求,来学习认证组件:
# 查询所有图书,不需要登录就能访问
# 查询单个图书,需要登录才能访问
由于两个接口,一个登录才能访问,一个不登录也能访问,所以最好把两个接口分开两个类写。
通过simpleRouter
生成路由,并实现对方法的映射。
自定义认证类
我们可以在视图类中添加authentications_classes
类属性来实现对整个视图类的认证校验。
只要是继承了GenericAPIView
的视图类中都有如下属性:
authentications_classes = [认证类,]
这个认证类需要我们自己写。
在app目录下,新键一个authenticate.py文件来存放我们自己写的认证类。
自己写的认证类,需要继承drf的认证基类BaseAuthentication
:
这个基类,有个authenticate
方法必须得重写否则会抛出异常:
通过query_params
方法获取get请求问号后面携带的token参数。根据请求中是否携带token,判断是否登录。
需要注意的是,当登录成功,要求固定返回两个值:
return (请求对应的用户,token)
当前用户没有登录则抛出AuthenticationFailed
异常。
这个异常从如下位置导入:
from rest_framework.exceptions import AuthenticationFailed
至此我们已经把自定义认证类写好了,接下来需要在我们的视图进行配置。
配置认证类
将我们写好的认证类添加到authentications_classes
类属性。
请注意,可以给一个视图添加多个认证类,他会从左到右执行。
这个视图类所有的方法,都需要经过认证类认证,才能执行。
我们通过认证类实现了上述需求。
全局配置
在django settings中配置可以实现全局生效(所有CBV)。
注意:
不要在django配置文件中乱导入不使用的东西,否则会报错:
这是因为先加载配置文件,再加载django项目。而app01是在django项目里面的,还没有成功加载,就导入,所以会报错。
局部禁用
也就是在authentication_classes
类属性写一个空列表, 这表示该CBV局部禁用认证。
认证组件使用步骤
# 1 写一个认证类,继承BaseAuthentication
# 2 重写authenticate方法,在该方法在中实现登录认证:token在哪带的?如果认证它是登录了
# 3 如果认证成功,返回两个值【返回None或两个值】
# 4 认证不通过,抛异常AuthenticationFailed
# 5 局部使用和全局使用
-局部:只在某个视图类中使用【当前视图类管理的所有接口】
class BookDetailView(ViewSetMixin, RetrieveAPIView):
authentication_classes = [LoginAuth]
-全局:全局所有接口都生效(登录接口不要)
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES':['app01.authenticate.LoginAuth']
}
-局部禁用:
class BookDetailView(ViewSetMixin, RetrieveAPIView):
authentication_classes = []
'''
重写和重载
重写:方法名和参数一样。
重载:方法名一样,参数不一样。
'''
认证类编写难点:
- token在请求的哪里携带?
- 如何获取用户上传的token?
- 如何认证用户登录了?
基于类中方法的认证(了解)
认证类是通过类属性配置的,所以一个认证类会对于整个视图类生效。但有时候我们会有如下的需求:
一个CBV类中,某些方法,进行认证,其他方法,不走认证。
要实现这个需求有如下方式:
- 方式一: 把我们写好的认证类添加到
action
装饰器的authentication_classes
参数中.
方式二: 使用原生django提供的装饰器
如果想给视图类中的方法添加装饰器, 并且这个装饰器是我们手写的函数装饰器时,这个装饰器不能直接给类中的方法添加.
而是需要使用django提供的一个装饰器来添加.
没错,通过装饰器来添加装饰器!导入
from django.utils.decorators import method_decorator
但是正常来说,应该把需要认证的接口和不需要认证的接口拆分开。(登录和未登录)
代码:
### 视图
# 查询所有
class BookView(ViewSetMixin, ListAPIView):
queryset = Book.objects.all()
serializer_class = BookSerializer
# 查询单个
class BookDetailView(ViewSetMixin, RetrieveAPIView):
queryset = Book.objects.all()
serializer_class = BookSerializer
# authentication_classes = [LoginAuth] # 需要写一个认证类,需要咱们写
### 认证类代码
class LoginAuth(BaseAuthentication):
def authenticate(self, request):
# 在这里实现认证,如果是登录的,继续往后走返回两个值,如果不是抛异常
# 请求中是否携带token,判断是否登录,放在地址栏中
token = request.query_params.get('token', None)
if token: # 前端传入token了,去表中查,如果能查到,登录了,返回两个值[固定的:当前登录用户,token]
user_token = UserToken.objects.filter(token=token).first()
if user_token:
return user_token.user, token
else:
# 没有登录抛异常
raise AuthenticationFailed('token认证失败')
else:
raise AuthenticationFailed('token没传')
### 路由代码
router.register('books', views.BookView, 'books')
router.register('books', views.BookDetailView, 'books')
权限类
是否有这种情况,你登录小视频网站,但是有些视频即使登录了,也无法观看,只有VIP才能观看。
这就是因为你没有权限,从上述例子也可以看出,权限是认证的后一层校验。
对于程序员来说,需要给接口设置权限:
# 即便登录成功了,有些接口,还是不能访问,因为没有权限
# 登录后,有的接口有权限访问,有的没有权限访问
通过一个需求,来学习权限类:
# 查询单个和查询所有接口,都要登录才能访问----》全局认证
-查询单个需要超级管理员才能访问
-查询所有,所有登录用户都能访问
前期准备
权限是一个字段,需要在user表中加入user_type字段。
通过user_type字段表示不同身份的用户。
备注: 如果模型字段使用了choice参数,就可以使用get_user_type_display
方法拿到字段对应的中文。
重写has_permission()
和认证类套路相似,写一个权限类:
这个权限类继承权限基类,需要重写基类的has_permission()
方法,在这个方法中实现权限认证。
需要注意的是这个方法的返回值:
- 如果有权限,
return True
- 如果没有权限,
return False
查看源码:
首先需要获取当前的用户,才能去数据库里查询该用户的user_type字段:
通过request.user可以拿到当前的用户,这个request.user属性是经过认证之后添加到request对象中的.
也就是认证函数authenticate
的第一个返回值:
认证方法的返回值第一个是当前用户,会放在request.user。在权限类中可以使用request.user将其拿出来。
判断权限:
通过类属性配置权限:
注意,权限和认证都可以配置多个。
添加权限不足信息
控制权限给前端的提示信息:
权限相关说明:
- 登录接口需要禁用权限,查询所有接口也需要禁用权限。
- 权限并不是这么简单,权限类的逻辑可以很复杂。用表保存用户的权限,当请求来了去权限表获取单个用户的权限.
权限组件使用步骤
# 1 写一个权限类,继承BasePermission
# 2 重写has_permission方法,在该方法在中实现权限认证,在这方法中,request.user就是当前登录用户
# 3 如果有权限,返回True
# 4 没有权限,返回False,定制返回的中文: self.message='中文'
# 5 局部使用和全局使用
-局部:只在某个视图类中使用【当前视图类管理的所有接口】
class BookDetailView(ViewSetMixin, RetrieveAPIView):
permission_classes = [CommonPermission]
-全局:全局所有接口都生效
REST_FRAMEWORK = {
'DEFAULT_PERMISSION_CLASSES': [
'app01.permissions.CommonPermission',
],
}
-局部禁用:
class BookDetailView(ViewSetMixin, RetrieveAPIView):
permission_classes = []
频率类
频率类控制某个接口访问的频率(次数)。
频率类常用于反爬,因为爬虫的请求次数太快,导致服务器压力很大, 服务器崩溃。
通过一个需求,来学习频率类:
查询所有的接口,同一个ip一分钟只能访问5次。
(可以通过IP地址控制、也可以用户控制访问频率)
频率类还是熟悉的套路。
这里继承simpleRateThrottle:
重写get_cache_key()
需要重写get_cache_key()
方法:
两种频率限制方法
这个方法返回什么,就以什么做频率限制:
(可以返回ip 或 用户ID)
如何获取客户端的ip地址?
使用reuquest.META
,
在request.META是一个字典, 这里面存放着请求头的各种数据。
以ip地址做限制:
以用户id做限制:
以电脑做限制,需要配合前端,将电脑的唯一标识传入后端。
配置固定的类属性scope
如果需要在视图类中配置频率需要做两件事:
频率类设置一个固定的类属性scope:
还需要配置django settings:
可以发现类属性的值,和这里的键有对应关系。5/m
:表示一分钟访问五次5/h
:表示一小时访问五次
他是会把字符串取第一个字符来判断是小时还是分钟。
所以也可以这样写:5/maya
---> 一分钟五次
局部使用在类中设置频率类:
服务重启会重新计算这个时间。
全局配置频率类:
跟上面不同, 需要进行两项配置:
局部禁用频率类:
频率组件使用步骤
# 1 写一个频率类,继承SimpleRateThrottle
# 2 重写get_cache_key方法,返回什么,就以什么做限制----》ip,用户id做限制
# 3 配置一个类属性:scope = 'book_5_m'
# 4 在配置文件中配置
'DEFAULT_THROTTLE_RATES': {
'book_5_m': '5/m',
},
# 5 局部使用和全局使用
-局部:只在某个视图类中使用【当前视图类管理的所有接口】
class BookDetailView(ViewSetMixin, RetrieveAPIView):
throttle_classes = [CommonThrottle]
-全局:全局所有接口都生效
REST_FRAMEWORK = {
'DEFAULT_THROTTLE_CLASSES': ['app01.throttling.CommonThrottle'],
}
-局部禁用:
class BookDetailView(ViewSetMixin, RetrieveAPIView):
throttle_classes = []
过滤类
restful规范中,要求了请求地址中带过滤条件。
- 5个接口中,只有一个接口需要有过滤和排序,也就是查询所有接口.
- 频率\认证\权限校验是多个接口都需要的.
需求:
查询 所有图书接口,查询以 红 开头的所有图书
内置过滤类 SearchFilter
class BookView(ViewSetMixin, ListAPIView):
queryset = Book.objects.all()
serializer_class = BookSerializer
# SearchFilter内置的,固定用法,模糊匹配
# 就有过滤功能了,指定按哪个字段过滤
filter_backends = [SearchFilter]
# search_fields = ['name'] # 可以按名字模糊匹配
search_fields = ['name','price'] # 可以按名字模糊匹配或价格模糊匹配
# 可以使用的搜索方式
http://127.0.0.1:8000/api/v1/books/?search=红 # name或price中只要有红就会搜出来
# 继承APIView如何写,完全自己写,麻烦,但是清晰
配置过滤类的方式:
必须继承GenericAPIView,如果是APIView需要自己写过滤相关逻辑.
在视图类中配置:
需要指定按照哪些字段进行过滤。
通过search_field
类属性,指定按照哪些字段过滤:
这个search_fields
是固定的写法,同时前端必须用search
提交查询参数。
可以按照多个字段,按照名字或价格字段模糊匹配:
示例:
只要名字或价格带939的, 都可以搜出来。
继承APIView怎么实现过滤?
全部都要自己写。
但是我们可以使用GenericAPIView自定义过滤类。
第三方过滤类 django-filter
# 安装:django-filter
class BookView(ViewSetMixin, ListAPIView):
queryset = Book.objects.all()
serializer_class = BookSerializer
permission_classes = []
authentication_classes = []
throttle_classes = []
filter_backends = [DjangoFilterBackend]
filterset_fields = ['name','price'] # 支持完整匹配 name=聊斋11&price=933
# 支持的查询方式
http://127.0.0.1:8000/api/v1/books/?price=939
http://127.0.0.1:8000/api/v1/books/?price=939&name=红楼猛
安装:
pip3.8 install django-filter -i https://pypi.tuna.tsinghua.edu.cn/simple
使用注意:
使用了第三方过滤类,就不使用search_fields
类属性,而是使用filterset_fields
类属性:
前端示例:
支持精确匹配。模糊匹配就是只要含有就可以匹配。
自定义过滤类
# 查询价格大于100的所有图书
http://127.0.0.1:8000/api/v1/books/?price_gt=100
#第一步; 定义一个过滤类,继承BaseFilterBackend,重写filter_queryset方法
class CommonFilter(BaseFilterBackend):
def filter_queryset(self, request, queryset, view):
# 在里面实现过滤,返回qs对象,就是过滤后的数据
price_gt = request.query_params.get('price_gt', None)
if price_gt:
qs = queryset.filter(price__gt=int(price_gt))
return qs
else:
return queryset
# 第二步:配置在视图类上
class BookView(ViewSetMixin, ListAPIView):
queryset = Book.objects.all()
serializer_class = BookSerializer
filter_backends = [CommonFilter] # 可以定制多个,从左往右,依次执行
需求:
# 查询价格大于100的所有图书
http://127.0.0.1:8000/api/v1/books/?price_gt=100
定义一个过滤类,继承BaseFilterBackend,重写filter_queryset方法
编写过滤类:
queryset参数存放所有模型对象。
配置多个过滤类,会依次从左往右执行:
如果想在自定义过滤类中实现类属性设置过滤字段,可以通过反射获取类中的属性:
view就是我们的视图类,可以从视图类中获取类属性。
踩坑:
模型类存放的是charfield charfield不支持__gt
排序类
使用drf内置的排序类.
# 内置的就够了
class BookView(ViewSetMixin, ListAPIView):
queryset = Book.objects.all()
serializer_class = BookSerializer
filter_backends = [OrderingFilter]
ordering_fields = ['price']
# 支持的查询方法:
http://127.0.0.1:8000/api/v1/books/?ordering=price
http://127.0.0.1:8000/api/v1/books/?ordering=-price
http://127.0.0.1:8000/api/v1/books/?ordering=-id,price
先将排序类配置到filter_backends
:
再设置排序字段:price
按照价格排序ordering=price
:
如下是按照价格升序.
按照价格逆序ordering=-price
:
支持多个排序:比如先按照价格排序,再按照购买量排序。
只需要在视图类配置排序字段:
ordering_field = ['price','sales']
前端格式如下:
http://127.0.0.1:8000/api/v1/books/?ordering=-price,sales
按照逗号隔开.(先按照价格逆序,在按照销售额升序)
分页类
# 分页,只有查询所有接口,才有分页
# drf内置了三个分页器,对应三种分页方式
#内置的分页类不能直接使用,需要继承,定制一些参数后才能使用
# 分页使用,自定义一个分页类(三种)
class CommonPageNumberPagination(PageNumberPagination):
page_size = 2 # 每页显示2条
page_query_param = 'page' # page=10 查询第10页的数据,每页显示2条
page_size_query_param = 'size' # page=10&size=5 查询第10页,每页显示5条
max_page_size = 5 # 每页最大显示10条
# LimitOffset
class CommonLimitOffsetPagination(LimitOffsetPagination):
default_limit = 3 # 每页显示2条
limit_query_param = 'limit' # limit=3 取3条
offset_query_param = 'offset' # offset=1 从第一个位置开始,取limit条
max_limit = 5
# offset=3&limit=2 0 1 2 3 4 5
# app 用下面
class CommonCursorPagination(CursorPagination):
cursor_query_param = 'cursor' # 查询参数
page_size = 2 # 每页多少条
ordering = 'id' # 排序字段
# 配置在视图类上即可
class BookView(ViewSetMixin, ListAPIView):
queryset = Book.objects.all()
serializer_class = BookSerializer
permission_classes = []
authentication_classes = []
throttle_classes = []
# 之前的东西一样用 ,内置的分页类不能直接使用,需要继承,定制一些参数后才能使用
# pagination_class = PageNumberPagination
#基本分页方式(基本是这种,网页端):http://127.0.0.1:8000/api/v1/books/?page=2&size=3
# pagination_class = LimitOffsetPagination
# 偏移分页 http://127.0.0.1:8000/api/v1/books/?limit=4&offset=1
# 从第一条开始,取4条
pagination_class = CommonCursorPagination
# 游标分页,只能下一页,上一页,不能跳到中间,但它的效率最高,大数据量分页,使用这种较好
只有查询所有接口,才需要分页。
drf内置三个分页器,对应三种分页方式。
数据10000条给前端,前端卡死了都,所以前端直接拿分好的数据。
类属性添加分页类:
分页属性只能配置一种分页方式。
内置的分页类不能直接用,而需要继承之后,自己定制一些参数,之后才能使用。
PageNumberPagination(网页)
源码:
需要设置四个类属性:
page_size可以写在配置文件中。
四个属性:
可以通过前端的size定制每页显示的条数。size的条数会受到最大条数的限制。
配置分页器:
响应中包含前页和后页:
第一页显示三条:
LimitOffsetPagination
也是配置类属性:
会将所有的数据排序:相当于做切片。
第一页:
从第一条数据开始拿,往后面拿4条数据:
CursorPagination(大数据,app)
游标分页源码:
具体使用:类属性重复会先用哪个?
游标分页,只能下一页,上一页,不能跳到中间,他的效率最高。适合大数据量的时候。
前面的分页, 是将数据从头开始检索,数据量越大,越慢,效率越低.
在分页时维护一个游标。
返回地址带链接:
游标分页默认的配置:
游标分页默认按照时间排序,如果没有在分页类中定义ordering属性就会报错。
这是因为ordering必须是表的字段,比如我们的表里肯定有id字段,所以可以设置ordering为'id':
【Django drf】认证类 权限类 频率类 过滤类 排序类 分页类的更多相关文章
- drf-认证、权限、频率、过滤、排序、分页
1.认证组件 1.1 局部认证 1.首先写两个接口,一个查询单个一个查询所有,我们利用视图扩展类和视图子类写在一个视图类上: views.py: from rest_framework.viewset ...
- drf权限,频率,过滤,排序,异常处理
目录 一.权限 1 权限源码分析 2 自定义权限类 3 内置权限类 二.频率 1 内置频率设置 三.过滤 四.排序 五.异常处理 一.权限 1 权限源码分析 # APIView---->disp ...
- rest-framework框架——认证、权限、频率组件
一.rest-framework登录验证 1.models.py添加User和Token模型 class User(models.Model): name = models.CharField(max ...
- restful(3):认证、权限、频率 & 解析器、路由控制、分页、渲染器、版本
models.py中: class UserInfo(models.Model): name = models.CharField(max_length=32) psw = models.CharFi ...
- Rest_Framework之认证、权限、频率组件源码剖析
一:使用RestFramwork,定义一个视图 from rest_framework.viewsets import ModelViewSet class BookView(ModelViewSet ...
- django-rest-framework 基础三 认证、权限和频率
django-rest-framework 基础三 认证.权限和频率 目录 django-rest-framework 基础三 认证.权限和频率 1. 认证 1.1 登录接口 1.2 认证 2. 权限 ...
- DRF 认证、权限、限制
DRF 认证.权限.限制 认证: 定义一个用户表和一个保存用户的Token表 # ======================day96======================= class ...
- drf框架 - 三大认证组件 | 认证组件 | 权限组件 | 频率组件
RBAC 基于用户权限访问控制的认证 - Role-Based Access Control Django框架采用的是RBAC认证规则,RBAC认证规则通常会分为 三表规则.五表规则,Django采用 ...
- django身份认证、权限认证、频率校验使用及源码分析
一. 身份认证源码分析 1.1 APIView源码的分析 APIView源码之前分析过https://www.cnblogs.com/maoruqiang/p/11135335.html,里面主要将r ...
- DRF比Django的认证和权限高在哪里
Django可以用LoginRequiredMixin和PermissionRequiredMixin给类视图添加认证和权限,DRF做了高级封装,提供了更简洁的实现方式.我们通过继续学习官网教程来进行 ...
随机推荐
- easyEZbaby_app
for循环,这里给它化简255-i+2-98-未知数x需要等于'0'对应的ASCII值48,那么求x的值,x=111-i,而i的值就是从0到14,这样便可以计算出15位的密码 所以写出来的脚本
- MIT实验警示:人类或需要人工智能辅助才能理解复杂逻辑
麻省理工实验揭示人类的天赋缺陷 麻省理工学院林肯实验室(MIT Lincoln Laboratory)的一项研究表明,尽管形式规范具有数学上的精确性,但人类并不一定能对其进行解释.换句话说就是,人类在 ...
- L2-029 特立独行的幸福
#include <bits/stdc++.h> using namespace std; bool isyifu[10010]; bool isunhappy[10010]; bool ...
- 3款高评价的.Net开发的WMS系统推荐
本文简介 WMS仓库管理系统是一款专业的仓库管理系统,旨在帮助企业实现仓储管理的智能化.信息化和自动化.通过该系统,企业可以实现对仓库的进货.出货.库存等各个环节的全面把控,提高仓储管理水平,降低运营 ...
- fianl详解(适合新手)
final 1.final是Java语言中的一个关键字 2.final表示最终的,不可变的. 3.final可以修饰变量以及方法,还有类等 4.final修饰的变量? 5.final修饰的方法? 6. ...
- [cnn]FashionMINST训练+保存模型+调用模型判断给定图片
import torch import torch.nn as nn import torch.nn.functional as F import torch.optim as optim impor ...
- springMvc_快速入门
概念:是一种基于Java实现mvc模型的轻量级web框架 优点:使用简单,开发便捷 灵活性强 总体来说springMvc就是来替代servlet的一种工具 快速入门: 1.创建maven-web ...
- 后端程序员必会的前端知识-05:React
五. React 1. React 基础 react 是前端三大框架之一 没有 vue 的基础更好,因为两者思想不太一样,不能用 vue 的习惯学习 react 需要有 js 基础,视频 19-58 ...
- java方法的定义与执行
java中的方法在类中定义. 定义方法格式: 访问修饰符 返回值类型 方法名(参数列表){ ... 执行内容 ... return 返回值; } 访问修饰符:表示方法在哪里能被 ...
- 酷表ChatExcel -北大出品免费自动处理表格工具
酷表ChatExcel是通过文字聊天实现Excel的交互控制的AI辅助工具,期望通过对表输入需求即可得到处理后的数据(想起来很棒),减少额外的操作,辅助相关工作人员(会计,教师等)更简单的工作.Cha ...