概述:
一.身份认证:
1: 配置身份认证后端:注意:只作用于DRF视图,对django视图不起作用。
主要有两个认证后端,一个是基本认证后端,一个是seesion认证后端。BasicAuthentication,SessionAuthentication
REST_FRAMEWORK = {
# 认证后端
'DEFAULT_AUTHENTICATION_CLASSES': (
# 'rest_framework.authentication.BasicAuthentication', # 基本认证 —— 请求的时候传递用户名和密码,进行身份认证
# 在drf视图(APIView)处理一个请求的过程中,会提取cookie中的sessionid,并在缓存中获取用户数据
'rest_framework.authentication.SessionAuthentication', # session认证
)
2:session缓存的配置:
CACHES = {
# 默认存储信息: 存到 0 号库
"default": {
"BACKEND": "django_redis.cache.mysql",
"NAME": "名字",
"PORT": 3306,
"USER":'root',
"HOST":'localhost',
"PASSWORD":'名字',
}
}
}
# session引擎
SESSION_ENGINE = "django.contrib.sessions.backends.cache"
# 指定session使用的缓存配置
SESSION_CACHE_ALIAS = "default"
3.1: 获取登陆的user—> user = request.user
@action(methods=['get'],detail=False, url_path="latest")
def latest(self, request, *args, **kwargs):
user = request.user
book = self.queryset.latest('bpub_date')
serializers = self.get_serializer(instance=book)
return Response(data=serializers.data)
3.2:创建一个用户
(django_env) python@ubuntu:~/Desktop/drf-demobook/demo_book$ python3 manage.py createsuperuser
Username (leave blank to use 'python'): renshanwen
Email address: 3131369886@qq.com
Password:
Password (12345678):
This password is too common.
This password is entirely numeric.
Bypass password validation and create user anyway? [y/N]: y
Superuser created successfully.
测试:现在是全局配置下:
登录状态下:访问127.0.0.1:8000/admin/进行注册用户,再访问127.0.0.1:8000/books/latest/
登录状态下:访问127.0.0.1:8000/books/latest/
删除cookie ;访问127.0.0.1: 8000/books/latest/
debug下发现没有认证,是匿名用户
4:自定义局部认证:
在视图中加入这个类属性:authentication_classes,指定身份认证后端,身份认证后端可以指定多个,并且局部认证后端会隐藏全局认证后端。身份认证如果有多个,只要有一个认证成功就可以。
from rest_framework.authentication import SessionAuthentication
authentication_classes = [SessionAuthentication]
二:权限后端:
1:全局配置
# 权限后端,有多个权限后端,遵循最严格的
'DEFAULT_PERMISSION_CLASSES': (
# 'rest_framework.permissions.IsAuthenticated', # 只有经过身份认证确定用户身份才能访问
# 'rest_framework.permissions.IsAdminUser', # is_staff=True才能访问 —— 管理员(员工)权限
'rest_framework.permissions.AllowAny', # 允许所有
# 'rest_framework.permissions.IsAuthenticatedOrReadOnly', # 有身份 或者 只读访问(self.list,self.retrieve)
)
2:几个认证后端的作用:
IsAuthenticated:被身份认证的: 只有身份被认证过才能访问DRF视图。
IsAdminUser: 是管理员身份: 只有管理员身份才能访问DRF视图,这里不是指的是超级管理员。
AllowAny: 任何权限都可以。
IsAuthenticatedOrReadOnly: 身份被认证了,或者只能读权限。
注意:如果权限都存在,则取最严格的权限,比如上面的如果都存在则是IsAdminUser。
3:局部配置:
在视图中加入:
局部配置会覆盖全局配置。
permission_classes = [IsAdminUser]
4:测试:假设是ISADMINUSER权限:
当前的管理员身份是超级管理员+普通管理员
此时分析:也就是现在只有是staff的普通管理员才能访问DRF视图。普通的无法访问。
现在数据库修改管理员身份,再次访问:
再次访问
三:流量限制:
1:全局配置
# 流量限制后端
'DEFAULT_THROTTLE_CLASSES': (
'rest_framework.throttling.AnonRateThrottle', # 限制匿名用户访问限制
'rest_framework.throttling.UserRateThrottle', # 非匿名用户访问限制
),
# 流量(请求次数)限制频率
'DEFAULT_THROTTLE_RATES': {
'anon': '3/day', # 匿名用户访问次数 3/day 3/hour 3/second 3/minute
'user': '5/day', # 非匿名用户访问次数
},
测试:访问127.0.0.1:8000/books/latest
不匿名访问5次后出现下面页面,匿名访问三次出现下面页面。
2:局部配置:
throttle_classes = [AnonRateThrottle, UserRateThrottle]
3:自定义限流后端:
3.1:配置文件设置自定义限流后端和限制规则
class HerosView(ModelViewSet):
queryset = HeroInfo.objects.all()
serializer_class = HeroInfoModelSerializers
throttle_scope = "heros"
# 自定义的身份认证
authentication_classes = [SessionAuthentication]
'DEFAULT_THROTTLE_CLASSES': (
'rest_framework.throttling.ScopedRateThrottle', # 自定义限流后端
),
'DEFAULT_THROTTLE_RATES': {
# 自定义限流后端的访问次数规则
'books': '3/day',
'heros': '5/day'
},
3.2:在不同的视图中指定不同的限制规则:
1:在boook视图中指定
throttle_scope = "books"
2:在hero视图中指定
throttle_scope = "heros"
注意:如果多个限流后端,那么也要遵循最严格的:谁的限制次数最少听谁的。
测试:访问books/latest/第四次就报错了。
测试英雄类:
注意:访问次数不是指的成功返回数据的此时,只要进行一次访问就记录一次。
4.过滤:Filtering:(过滤只针对序列化返回多个)
1.安装扩展包
pip install django-filter
2:在配置文件中增加过滤后端的设置:
注册应用:
INSTALLED_APP = [
# ....
'django_filters',
]
REST_FRAMEWORK配置项对"drf接口"进行全局配置
REST_FRAMEWORK = {
# 过滤后端,针对所有资源视图的self.list接口(获取列表数据),进行过滤动作
'DEFAULT_FILTER_BACKENDS': (
'django_filters.rest_framework.DjangoFilterBackend',
)
}
6
3:过滤的规则怎么设置??
在视图中设置:
filterset_fields = ['bread', 'bcomment', 'btitle']
4.测试:
测试情况一:过滤阅读量是200的:
情况二:过滤出阅读量是200,并且评论量是300的数据:
五:排序:
1:在过滤后端中指定排序后端的路径:
REST_FRAMEWORK = {
# ......
# 过滤后端,针对所有资源视图的self.list接口(获取列表数据),进行过滤动作
'DEFAULT_FILTER_BACKENDS': (
# 'django_filters.rest_framework.DjangoFilterBackend', # 指定字段过滤
'rest_framework.filters.OrderingFilter', # 排序后端(过滤)
)
}
2:在视图中指定根据哪个字段进行过滤?
ering_fields = [‘bread’, ‘bcomment’, ‘bpub_date’]
测试:
六:分页
1:分页的两种逻辑:
1.1:按照每页pagesize个,page取第几个。GET + /books/?page=1&pagesize=5
1.2: 从第一个数据开始,偏移offset条数据,取limit条数据。
2:使用PageNumberPagination进行分页:
2.1:全局配置:
REST_FRAMEWORK = {
# PageNumberPagination: 按照每页pagesize个划分,取第page页
'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',
'PAGE_SIZE': 3 # 后端定义默认每页数目
}
测试:
2.2:局部配置:
在视图中增加:
pagination_class = PageNumberPagination
2.3:自定义分页后端:
需要重写PageNumberPagination
class MyPageNum(PageNumberPagination):
# 约定:/books/?page=1&pagesize=5
# 通过类属性,定义查询字符串参数
page_query_param = 'page' # 指定查询字符串参数key为'page',传递取第几页
page_size_query_param = 'pagesize' # 指定查询字符串参数key为'pagesize',传递每页数目
page_size = 5 # 指定后端默认按照每页几个划分
max_page_size = 10 # 每页数目的最大值
另外视图中换成我们自己定义的
pagination_class = MyPageNum
测试:
3.2: 局部配置
from rest_framework.pagination import PageNumberPagination,LimitOffsetPagination
class HerosView(ModelViewSet):
queryset = HeroInfo.objects.all()
serializer_class = HeroInfoModelSerializer
pagination_class = LimitOffsetPagination
3.3:自定义分页后端:
class MyLimitOffset(LimitOffsetPagination):
# 约定:/books/?offset=5&limit=2
# 通过类属性,定义查询字符串参数
pagination_class = LimitOffsetPagination
limit_query_param = 'limit'
offset_query_param = 'offset'
default_limit = 2
max_limit = 10
class HerosView(ModelViewSet):
queryset = HeroInfo.objects.all()
serializer_class = HeroInfoModelSerializer
pagination_class = MyLimitOffset