1、序列化数据:
创建serializers.py的python文件
从rest_framework里导入serializers类:
from rest_framework import serializers
class LoginSerializer(serializers.Serializer):
email = serializers.EmailField(required=True, error_messages={"required": "请输入邮箱!"})
password = serializers.CharField(max_length=20, min_length=6)
# 重写校验
def validate(self, attrs):
email = attrs.get('email')
password = attrs.get('password')
if email and password:
user = OAUser.objects.filter(email=email).first()
if not user:
raise serializers.ValidationError("请输入正确的邮箱!")
if not user.check_password(password):
raise serializers.ValidationError("请输入正确的密码!")
# 判断状态
if user.status == UserStatusChoices.UNACTIVE:
raise serializers.ValidationError("该用户尚未激活!")
elif user.status == UserStatusChoices.LOCKED:
raise serializers.ValidationError("该用户已被锁定,请联系管理员!")
# 为了节省执行SQL语句的次数,这里我们把user直接放到attrs中,方便在视图中使用
attrs['user'] = user
else:
raise serializers.ValidationError('请传入邮箱和密码!')
return attrs
2、创建authentications.py文件
安装jwt:
pip install PyJWT
import jwt
import time
from django.conf import settings
from rest_framework.authentication import BaseAuthentication, get_authorization_header
from rest_framework import exceptions
from jwt.exceptions import ExpiredSignatureError
from .models import OAUser
def generate_jwt(user):
expire_time = time.time() + 60 * 60 * 24 * 7
return jwt.encode({"userid": user.pk, "exp": expire_time}, key=settings.SECRET_KEY)
class UserTokenAuthentication(BaseAuthentication):
def authenticate(self, request):
# 这里的request:是rest_framework.request.Request对象
return request._request.user, request._request.auth
class JWTAuthentication(BaseAuthentication):
keyword = 'JWT'
def authenticate(self, request):
auth = get_authorization_header(request).split()
if not auth or auth[0].lower() != self.keyword.lower().encode():
return None
if len(auth) == 1:
msg = "不可用的JWT请求头!"
raise exceptions.AuthenticationFailed(msg)
elif len(auth) > 2:
msg = '不可用的JWT请求头!JWT Token中间不应该有空格!'
raise exceptions.AuthenticationFailed(msg)
try:
jwt_token = auth[1]
jwt_info = jwt.decode(jwt_token, settings.SECRET_KEY, algorithms='HS256')
userid = jwt_info.get('userid')
try:
# 绑定当前user到request对象上
user = OAUser.objects.get(pk=userid)
setattr(request,'user', user)
return user, jwt_token
except:
msg = '用户不存在!'
raise exceptions.AuthenticationFailed(msg)
except ExpiredSignatureError:
msg = "JWT Token已过期!"
raise exceptions.AuthenticationFailed(msg)
3、登录的话涉及增删改查,所以直接用rest_framework提供的APIView
导入:
from rest_framework.views import APIView
from .serializers import LoginSerializer, UserSerializer
from .authentications import generate_jwt
from rest_framework.response import Response
class LoginView(APIView):
def post(self, request):
# 1. 验证数据是否可用
serializer = LoginSerializer(data=request.data)
if serializer.is_valid():
user = serializer.validated_data.get('user')
user.last_login = datetime.now()
user.save()
# 生成token
token = generate_jwt(user)
return Response({'token': token, 'user': UserSerializer(user).data})
else:
# person = {"username": "张三", "age": 18}
# person.values() = ['战三', 18] dict_values
detail = list(serializer.errors.values())[0][0]
# drf在返回响应是非200的时候,他的错误参数名叫detail,所以我们这里也叫做detail
return Response({"detail": detail}, status=status.HTTP_400_BAD_REQUEST)
User对象实例化 使用serializers.ModelSerializer:
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = 0AUser
fields = "__all__"
嵌套定义:
class DepartmentSerializer(serializers.ModelSerializer):
class Meta:
model = OADepartment
fields = "__all__"
class UserSerializer(serializers.ModelSerializer):
department = DepartmentSerializer()
class Meta:
model = OAUser
# fields = "__all__"
exclude = ('password', 'groups', 'user_permissions')