认证类和频率类
认证类
1.认证类编写
创建新的.py文件
from .models import User, Token
from rest_framework.authentication import BaseAuthentication
from rest_framework.exceptions import AuthenticationFailed
class LoginAuth(BaseAuthentication):
def authenticate(self, request):
# 从请求中获取token
token = request.query_params.get('token')
# 查询token是否存在
user_token = Token.objects.filter(token=token).first()
if user_token:
# 说明用户存在,还回登录用户和token
""" 固定还回这两个值 """
return user_token.uId, token
else:
# 如果用户未登录,报异常
raise AuthenticationFailed('小伙子,你没有登录,不能访问!')
2.认证类使用
在需要认证的视图类中注册
# 首先导入认证类
from .auth import LoginAuth
# 局部使用
class BookView(APIView):
authentication_classes = [LoginAuth, ]
# 局部禁用
class BookView(APIView):
authentication_classes = []
# 全局使用
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES':['app01.auth.LoginAuth',]
}
权限类
1.权限类编写
from rest_framework.permissions import BasePermission
class PermissionAuth(BasePermission):
# 1.自定义还回提示信息
# 2.修改配置之文件(setting.py)
message = '你没有权限'
def has_permission(self, request, view):
# 一. user_type 是在表模型自定义的字段。
# 下面代码查询user时,可能因为用户未登录,出现错误,可以使用异常捕获处理,还回 False.(表示无权限)。
if request.user.user_type == 1:
# 还回布尔值
return True
else:
# 二. get_user_type_display() ===> get_字段名_display() 获取选择序号所对应的中文
# 三. user_type 获取序号
# 《一,二,三,不明白的话可以看下面的图》
self.message = f'{request.user.get_user_type_display()}, 你当前没有权限'
# 还回布尔值
return False
2.权限类使用
在需要认证的视图类中注册
# 首先导入权限类
from .auth import PermissionAuth
# 局部使用
class BookView(APIView):
permission_classes = [PermissionAuth,]
# 局部禁用
class BookView(APIView):
permission_classes = []
# 全局使用
REST_FRAMEWORK = {
'DEFAULT_PERMISSION_CLASSES':['app01.auth.PermissionAuth',]
}
频率类
1.内置方法
(1)频率类步骤
-第一步: 写一个类,继承SimpleRateThrottle
-第二步: 重写get_cache_key方法
-第三步: return 一个返回值 =====》 返回什么,就以什么做限制
-第四步: 写一个类属性
# 配置 scope 需要执行第五步的配置。
scope = 'lqz'
或
# 配置 rate 就不用执行第五步的配置。
rate = '5/minute'
-第五步:配置文件中配置
REST_FRAMEWORK = {
"DEFAULT_THROTTLE_RATES": {
# 第四步中 scope 对应的值
'lqz':'3/m' # 数字/s m h d ====》 每时间内可以触发 n 次
},
}
-第六步:局部和全局使用
局部使用:视图类中
class BookView(APIView):
throttle_classes = [IPThrottle, ]
全局使用:配置文件
REST_FRAMEWORK = {
"DEFAULT_THROTTLE_RATES": {
# 频率类中scope对应的值
'lqz': '3/m' # 数字/s m h d
},
'DEFAULT_THROTTLE_CLASSES':['app01.throttling.IPThrottle',]
}
(2)频率类编写
from rest_framework.throttling import SimpleRateThrottle
class IPThrottle(SimpleRateThrottle):
scope = '5_min'
或
rate = '5/minute'
def get_cache_key(self, request, view):
# 如果未登录,request.user值为None,此类不生效
print(request.user.id)
# 此类还回什么,就以什么做限制
# eg: 以 "用户" 做限制,那就返回 user.id
# 以 "ip" 做限制,那就返回 户端ip地址
# 获取客户端的地址 request.META.get('REMOTE_ADDR')
return request.META.get('REMOTE_ADDR')
(3)视图类编写
class BookView(APIView):
throttle_classes = [IPThrottle, ]
def get(self, request):
return Response('ok')
# 1.配置中文提示信息, 2.配置文件中也行
def throttled(self, request, wait):
from rest_framework.exceptions import Throttled
class MyThrottled(Throttled):
default_detail = '超限制乐'
extra_detail_singular = '还有 {wait} 描述.'
extra_detail_plural = '出了 {wait} 秒.'
raise MyThrottled(wait)
2.自定义方法 (继承 BaseThrottle)
(1)频率类编写
from rest_framework.throttling import BaseThrottle
import time
class MyThrittle(BaseThrottle):
USERIP_TIME = {}
def __init__(self):
# 设置默认值,
self.disiply = None
# 重写该方法需要还回 True 或 False
def allow_request(self, request, view):
# 获取登录用户 ip
user_ip = request.META.get('REMOTE_ADDR')
newTime = time.time()
if user_ip not in self.USERIP_TIME:
self.USERIP_TIME[user_ip] = [newTime, ]
return True
while self.USERIP_TIME[user_ip] and newTime - self.USERIPip_TIME[user_ip][-1] > 10:
self.USERIP_TIME[user_ip].pop()
# 用户访问时间数组
self.disiply = self.USERIP_TIME[user_ip]
if len(self.USERIP_TIME[user_ip]) < 3:
self.USERIP_TIME[user_ip].insert(0, newTime)
return True
else:
return False
# 重写 wait 方法
def wait(self):
newTime = time.time()
# 还回剩余多少秒后可以访问
return 10 - (newTime - self.disiply[-1])
排序
1..视图类
前提是继承 GenericAPIView 及其子类。
from rest_framework.viewsets import GenericViewSet
from rest_framework.mixins import ListModelMixin
class BookView(GenericViewSet, ListModelMixin):
serializer_class = BookSerializer
queryset = Book.objects.all()
# """ 固定写法 """
filter_backends = [OrderingFilter, ]
# 填写需要排序的字段
ordering_fields = ['price', 'id']
2.路由
from rest_framework.routers import SimpleRouter
router = SimpleRouter()
router.register('book', views.BookView, 'book')
urlpatterns = []
urlpatterns += router.urls
3.访问方式
# 按价格升序排序
http://127.0.0.1:8006/book/?ordering=price
# 按价格降序排序
http://127.0.0.1:8006/book/?ordering=-price
# 按价格升序排序,价格相同则按id升序排序
http://127.0.0.1:8006/book/?ordering=price,id
过滤
1.内置方法
模糊查询,不能指定查询某个字段
(1)视图类
from rest_framework.viewsets import GenericViewSet
from rest_framework.mixins import ListModelMixin
class BookView(GenericViewSet, ListModelMixin):
serializer_class = BookSerializer
queryset = Book.objects.all()
# 可以添加多个方法
filter_backends = [SearchFilter, ]
search_fields = ['name', 'price']
(2)访问方式
http://127.0.0.1:8000/book?search=恋爱大陆
(3)查询方式
search = xx ----> 具体查询是 name like xx or price like xx
2.第三方模块
(1)下载
pip3 install django-filter
(1)视图类
from django_filters.rest_framework import DjangoFilterBackend
class BookView(GenericViewSet, ListModelMixin):
serializer_class = BookSerializer
queryset = Book.objects.all()
filter_backends = [DjangoFilterBackend, ]
filter_fields = ['name', 'price']
3.自定义过滤器
(1)过滤器类
from rest_framework.filters import BaseFilterBackend
class FilterFields(BaseFilterBackend):
# 重写 filter_queryset 方法
def filter_queryset(self, request, queryset, view):
# 请求中获取过滤字段
name = request.query_params.get('name')
# 过滤名字里包含 name(过滤字段)的数据
queryset = queryset.filter(name__contains=name)
return queryset
(1)视图类
from .throttling import FilterFields
class BookView(GenericViewSet, ListModelMixin):
serializer_class = BookSerializer
queryset = Book.objects.all()
# 固定写法
filter_backends = [FilterFields, ]