多方式登录接口

视图类

新写法-------> res.is_valid (raise_exception=True)

from rest_framework.viewsets import ViewSet, GenericViewSet
from .serialize import CommentMulLoginSerializer
from luffy_api.utils.comment_response import MyResponse
from rest_framework.decorators import action

# 编写视图类
class MultimodeLoginView(GenericViewSet):
    # 重写路由方法
    @action(methods=['POST', 'GET'], detail=False, url_path='login', url_name='login')
    def mul_login(self, request):


        """

        1 老写法
        username=request.data.get('username')
        password=request.data.get('password')
        查询用户,
        UserInfo.objects.filter(username=username,password=password)
        签发token
        返回

        """


        """ 新写法---> 仿 jwt 模块登录源码 """
        # 对数据进行反序列化
        res = CommentMulLoginSerializer(data=request.data)

        # raise_exception=True 的含义是,一旦检出错误,自动return,不用我们手写return
        res.is_valid(raise_exception=True)

        username = res.context['username']
        token = res.context['token']
        icon = res.context['icon']

        # 自己封装的 Response 方法
        return MyResponse(username=username, token=token, icon=icon)

序列化类

★★★★★ 字段默认唯一性,需将字段修改

from rest_framework.exceptions import ValidationError
from rest_framework_jwt.settings import api_settings
from rest_framework import serializers
from django.contrib import auth
import re

jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER
jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER

from .models import UserInfo
uni

class CommentMulLoginSerializer(serializers.ModelSerializer):
    username = serializers.CharField()

    class Meta:
        model = UserInfo

        ####### 因为此字段相当于映射为  username = serializers.CharField( unique=True )
        #######                       password = serializers.CharField( unique=True )
        ####### 登陆的话,执行此校验规则时,会向数据库查找此字段, 发现数据库已经有了此字段, 会报错,因此需将 unique 改为 False || 重写字段
        fields = ['username', 'password']

    # 获取用户
    def _get_user(self, attrs):
        username = attrs.get('username')
        password = attrs.get('password')
        if re.match(r'^(13[0-9]|14[01456879]|15[0-35-9]|16[2567]|17[0-8]|18[0-9]|19[0-35-9])\d{8}$', username):

            # """authenticate只能是对 用户名-密码 两个字段进行验证, 别的字段就直接还回,不会验证。------> 源码分析的结果 """
            # 所以这里不能用  authenticate  对 用户名-密码 以外的字段做验证
            user = UserInfo.objects.filter(mobile=username).first()


        elif re.match(r'^.+@.+$', username):
            # """authenticate只能是对 用户名-密码 两个字段进行验证, 别的字段就直接还回,不会验证。------> 源码分析的结果 """
            # 所以这里不能用  authenticate  对 用户名-密码 以外的字段做验证
            user = UserInfo.objects.filter(email=username).first()


        else:
            user = auth.authenticate(username=username, password=password)


        if user and user.check_password(password):
            return user

        else:
            raise ValidationError('用户名或密码错误!')               # 捕获异常

    # 签发token
    def _get_token(self, user):
        try:

            payload = jwt_payload_handler(user)                     # 根据当前登录用户荷载
            token = jwt_encode_handler(payload)                     # 根据荷载生成token

            return token
        except Exception as e:
            raise ValidationError(str(e))

    def validate(self, attrs):

        # 用户验证
        user = self._get_user(attrs)

        # 签发token
        token = self._get_token(user)

        self.context['token'] = token
        self.context['username'] = user.username
        self.context['icon'] = 'http://127.0.0.1:8000/media/' + str(user.icon)

        return attrs

posted @ 2023-04-22 22:37  codegjj  阅读(45)  评论(0)    收藏  举报