Django+Vue3前后端分离学习(四)(登录功能实现)

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')
相关推荐
效率客栈老秦4 分钟前
Python Trae提示词开发实战(2):2026 最新 10个自动化批处理场景 + 完整代码
人工智能·python·ai·prompt·trae
IT 行者9 分钟前
告别硬编码!Spring Boot 优雅实现 Controller 路径前缀统一管理
数据库·spring boot·python
No0d1es13 分钟前
2025年12月 GESP CCF编程能力等级认证Python五级真题
开发语言·python·青少年编程·等级考试·gesp·ccf
Ro Jace13 分钟前
基于互信息的含信息脑电图自适应窗口化情感识别
人工智能·python
风送雨13 分钟前
Go 语言进阶学习:第 2 周 —— 接口、反射与错误处理进阶
开发语言·学习·golang
蓝程序14 分钟前
Spring AI学习 程序接入大模型(框架接入)
人工智能·学习·spring
dear_bi_MyOnly16 分钟前
数据分析常用操作汇总
大数据·python·数据挖掘·数据分析·学习方法
MC皮蛋侠客16 分钟前
使用 Sphinx 构建高质量 Python 文档
python·全文检索·sphinx
YangYang9YangYan17 分钟前
2026高职大数据专业:数据分析学习的价值与前景
大数据·学习·数据分析
CyanMind18 分钟前
强化学习观测项详解之——重力投影
学习·机器人