自定义认证类
# 认证类文件
from rest_framework.authentication import BaseAuthentication
from rest_framework.exceptions import AuthenticationFailed
from app01 import models
# token 的两种方式 第一种是放在get请求地址栏中 一种是放在请求头中 在Meta中取
# 如果不继承 BaseAuthentication 则是还要重写 authenticate_header 方法
# 但是 authenticate 方法是必写的
class AuthLogin(BaseAuthentication):
def authenticate(self,request):
user_token = request.GET.get('token') or request.META.get('HTTP_TOKEN')
token = models.User_Token.objects.filter(token=user_token).first()
if token:
# 通过token拿到当前登录用户
user = token.user
# 必须返回用户和token串 不然后续视图类中给前端的时候拿不到了
return user,token
else:
raise AuthenticationFailed('您没有登录')
# # 如果不继承 BaseAuthentication 则是需要重写这个方法
# def authenticate_header(self,request):
# pass
# 视图类
from rest_framework.generics import GenericAPIView
from app01.serializer import BookSerializer
class LoginView(APIView):
def post(self,request):
username = request.data.get('username')
password = request.data.get('password')
user = models.Userinfo.objects.filter(username=username, password=password).first()
if user:
import uuid
token = uuid.uuid4()
# user=user 先查询有没有这个用户信息 有就更新 没有defaults={'token':token} 修改
models.User_Token.objects.update_or_create(defaults={'token': token}, user_id=user.pk)
return Response({'code': 200, 'msg': '登录成功', 'token': token})
return Response({'code': 201, 'msg': '用户或密码错误'})
class Bookview(GenericAPIView):
# 局部配置只需要在这里 写上即可 只有携带token才能访问这个接口
authentication_classes = [AuthLogin]
queryset = models.Book.objects.all()
serializer_class = BookSerializer
def get(self,request):
object_list = self.get_queryset() # 一定要加上括号
# 序列化的参数和 APIView 一样的
ser = self.get_serializer(instance=object_list, many=True)
return Response({'code': 100, 'msg': '查询所有成功', 'result': ser.data})
"""
1 全局使用(所有接口,都需要登录才能访问)
-在配置文件中
REST_FRAMEWORK = {
[ "DEFAULT_AUTHENTICATION_CLASSES": ["app01.MyAuthen.LoginAuth", ]
}
2 局部使用
-在想局部使用的视图类上
authentication_classes = [MyAuthen.LoginAuth,]
3 局部禁用
-在想禁用的视图类上
authentication_classes = []
"""
自定义权限类
from app01 import models
from rest_framework.views import APIView
from rest_framework.response import Response
from app01.auth_class import AuthLogin
from rest_framework.generics import GenericAPIView
from app01.serializer import BookSerializer
class LoginView(APIView):
def post(self,request):
username = request.data.get('username')
password = request.data.get('password')
user = models.Userinfo.objects.filter(username=username, password=password).first()
if user:
import uuid
token = uuid.uuid4()
# user=user 先查询有没有这个用户信息 有就更新 没有defaults={'token':token} 修改
models.User_Token.objects.update_or_create(defaults={'token': token}, user_id=user.pk)
return Response({'code': 200, 'msg': '登录成功', 'token': token})
return Response({'code': 201, 'msg': '用户或密码错误'})
from app01 import auth_class
class Bookview(GenericAPIView):
# 认证类写在前面 只有登录之后带着token过来才能访问这个接口
authentication_classes = [AuthLogin]
# 权限类
permission_classes = [auth_class.Authority]
queryset = models.Book.objects.all()
serializer_class = BookSerializer
def get(self,request):
object_list = self.get_queryset()
ser = self.get_serializer(instance=object_list, many=True)
return Response({'code': 100, 'msg': '查询所有成功', 'result': ser.data})
from rest_framework.permissions import BasePermission
class Authority(BasePermission):
def has_permission(self,request, view):
try:
user_admin = request.user.user_admin
if user_admin == 2:
return True
else:
# 通过 get_字段名——display() 取出 chionse对应的字符
self.message = '你是 %s,没有权限访问' % request.user.get_user_admin_display()
return False
except Exception:
# 这个是返回给前端的提示 如果不重写 使用默认的
self.message = '你没有登录,没有权限访问'
self.code = {'code':404}
return False
# 全局配置和局部配置
REST_FRAMEWORK = {
"DEFAULT_AUTHENTICATION_CLASSES": ["app01.MyAuthen.LoginAuth", ]
"DEFAULT_PERMISSION_CLASSES": ["app01.MyAuthen.SuperPermission", ]
}
局部配置
-局部禁用
class Bookview(GenericAPIView):
permission_classes = []
pass0
choices的使用
get_字段名_display()的方法,该方法获得choice字段对应的数据
class Userinfo(models.Model):
choices_admin = ((1, '普通用户'), (2, '管理员用户'), (3, '二笔用户'))
username = models.CharField(max_length=32)
password = models.CharField(max_length=64)
user_admin = models.IntegerField(default=1, choices=choices_admin)
from rest_framework import serializers
class Usernameserializer(serializers.ModelSerializer):
choices_user = serializers.CharField(max_length=32,source='get_choices_admin_display()')
class Meta:
model = models.Userinfo
fields = ['username', 'password', 'user_admin','choices_user']
频率限制
# 视图类
class Bookview(GenericAPIView):
# 认证类写在前面 只有登录之后带着token过来才能访问这个接口
authentication_classes = [AuthLogin]
# # 权限类
permission_classes = [auth_class.Authority]
# 频率限制
throttle_classes = [auth_class.MySimpleThrottle]
queryset = models.Book.objects.all()
serializer_class = BookSerializer
def get(self,request):
object_list = self.get_queryset()
ser = self.get_serializer(instance=object_list, many=True)
return Response({'code': 100, 'msg': '查询所有成功', 'result': ser.data})
# 重写频率类
from rest_framework.throttling import SimpleRateThrottle
class MySimpleThrottle(SimpleRateThrottle):
scope = 'time'
# get_cache_key 这个方法必须重写
def get_cache_key(self, request, view):
# ip = request.META.get('REMOTE_ADDR')
# return ip # 两种都是一样的
# 以ip限制 内部的
return self.get_ident(request)
# setting.py
REST_FRAMEWORK = {
'DEFAULT_THROTTLE_RATES' : {
'time':'10/m'# key跟scope对应,value是一个时间 m是一分钟 d是一个月 h是一小时
}
}
# 局部配置 就是
throttle_classes = []