• Python实战项目6-后端多方式登录接口/手机登录接口


    为开源项目共享代码

    步骤:
    	1先fork开源项目
    	2clone下来,修改代码,进行提交
    	3提交pr,等作者同意
    

    Pycharm 使用Git

    右键文件会列出Git命令
    image.png

    登录注册功能分析

    多方式登录接口:用户名/手机号/邮箱 + 密码都可以登陆
    
    发送手机验证码接口 (借助于第三方短信平台)
    
    短信登录接口
    
    注册接口
    

    手机号是否存在接口

    校验手机号是否存在
    user/urls.py

    路由层
    from django.urls import path, include
    from rest_framework.routers import SimpleRouter
    from . import views
    
    router = SimpleRouter()
    router.register('user',views.UserView,'user')
    urlpatterns = [
        path('',include(router.urls)) // 
    ]
    # urlpatterns += router.urls	
    

    user/views.py

    from rest_framework.viewsets import ViewSet
    from rest_framework.exceptions import APIException
    from rest_framework.decorators import action
    from utils.response import APIResponse
    from .models import UserInfo
    class UserView(ViewSet):
        @action(methods=['get'], detail=False)
        def check_mobile(self, request):
            try:
                # 如果布报错就说明手机号存在
                mobile = request.query_params.get('mobile')
                UserInfo.objects.get(mobile=mobile)
                return APIResponse('手机号存在')
            except Exception as e:
                # raise e  也可以直接返抛出异常,就可以被全局异常捕获到
                raise APIException('手机号不存在!')
    

    视图函数模板

    from restframework.response import APIresponse
    def send_sms(self, request, *args, **kwargs):
            try:
                # 放心大胆写
            except Exception as e:
                raise e
            return APIResponse()
    

    多方式登录接口

    使用用户名/手机号/邮箱+密码登录
    发送post请求到后端{"username":"xxx","password":"123"}

    # 登录逻辑
    1取出前端传入的用户名和密码
    2通过用户名和密码去数据库查询
    3查到了,签发token
    4返回前端
    
    将逻辑放入序列化类中..
    

    视图类

    • ser_obj.context >> 序列化类与视图类沟通的桥梁(本质上是个字典)
    from rest_framework.viewsets import ViewSet
    from .serializer import UserMulLoginSerializer, MobileLoginSerializer
    from rest_framework.decorators import action
    from utils.response import APIResponse
    from .models import UserInfo
    class UserView(ViewSet):
        @action(methods=['post'], detail=False, )
        def login(self, request):
            return self.common_login()
    
            
        def _get_serializer(self, data): # 因为我们有短信登录和多方式登录,可以将序列化类封装到函数中通过判断获取
            # 判断请求方式返回不同的序列化类
            res = self.request.META.get('PATH_INFO')
            #  PATH_INFO 可以拿到请求的路径信息
            if res == '/api/v1/userinfo/user/mobile_login/':
                return MobileLoginSerializer(data=data)
            return UserMulLoginSerializer(data=data)
    
        def common_login(self):  
            ser_obj = self._get_serializer(data=self.request.data)
            # 执行这句话,会走字段自己的校验,局部钩子,全局钩子
            ser_obj.is_valid(raise_exception=True)
            token = ser_obj.context.get('token')
            # 有了序列化类对象,通过  对象.context 就可以拿到值
            icon = ser_obj.context.get('icon')
            username = ser_obj.context.get('username')
            return APIResponse(token=token, icon=icon, username=username)
    

    序列化类

    from rest_framework import serializers
    from .models import UserInfo
    from utils.common_serializer import Verification
    
    
    class UserMulLoginSerializer(serializers.ModelSerializer, Verification):
        # 全局钩子中有很多重复代码,我们直接将其封装到 (多方式登录和手机登录都可以使用)
        # utils目录下的common_serializer.py中
        username = serializers.CharField()
        # 由于序列化类校验时会先走字段自己的校验,Mobile字段我们又设置了unique=True属性
        # 所以如果我们请求来到了字段自己的校验就不会通过,我们需要重写该字段
    
        class Meta:
            model = UserInfo
            fields = ['username', 'password']  
    
        def validate(self, attrs): 
            attrs = self._validate(attrs)
            return attrs  # 全局钩子必须返回校验后的数据
    如果没有通过序列化类的校验,需抛出异常
    我们又封装了全局捕获异常,所以就直接抛出即可
    

    utils/common_serializer/Verification

    import re
    from django.contrib.auth import authenticate
    from rest_framework.exceptions import ValidationError,APIException
    from django.core.cache import cache
    from rest_framework_jwt.serializers import jwt_payload_handler, jwt_encode_handler
    from user.models import UserInfo
    class Verification():
        def _get_token(self, user_obj):
            pay_load = jwt_payload_handler(user_obj)
            token = jwt_encode_handler(pay_load)
            return token
        def _validate(self,attrs):
            user_obj = self._get_user(attrs)
            token = self._get_token(user_obj)
            self.context['token'] = token  # self 是 序列化类对象 所以可以点context传值进去
            self.context['username'] = user_obj.username
            self.context['icon'] = 'http://127.0.0.1:8000/media/' + str(user_obj.icon)
            return attrs
        def _get_user(self, attrs):
            username = attrs.get('username')
            password = attrs.get('password')
            mobile = attrs.get('mobile')
            if mobile:
                if not re.match(r'^1[3-9][0-9]{9}$', mobile):
                    raise ValidationError('手机号格式输入错误')
                code = attrs.get('code')
                old_code = cache.get('sms_code_%s' % mobile)
                if code == old_code:
                    return UserInfo.objects.filter(mobile=mobile).first()
                raise APIException('验证码错误')
            
            if re.match(r'^1[3-9][0-9]{9}$', username):
                user_obj = UserInfo.objects.filter(mobile=username).first()
                if user_obj.check_password(password) and user_obj:
                    return user_obj
                raise ValidationError('用户名或密码错误')
                # user_obj = authenticate(mobile=username, password=password)
            elif re.match(r'^.+@.+$', username):
                user_obj = authenticate(email=username, password=password)
            else:
                user_obj = authenticate(username=username, password=password)
            if not user_obj:
                raise ValidationError('用户名或密码错误')
            return user_obj
                
    

    腾讯云短信申请

    • 发送短信接口,借助于第三方短信平台

    我们在使用云短信前需要自己申请Vx公众号(个人的即可)

    • 使用腾讯短信

    微信扫码登录

    • 搜索短信:
    • 创建短信签名:公众号注册,提交等待审核
    • 创建短信正文模版
    • 等待审核
    • 发送短信(api接口 SDK)

    API: 咱们学习过的API接口,写起来比较麻烦,自己分析接口,对上即可
    SDK:集成开发工具包,分语言,java,python,go
    使用python 对api进行封装成包
    以后我们只需要,安装包,导入包,包名.发送短信,传入参数,就可以发送了
    pip install tencentcloud-sdk-python


    __EOF__

  • 本文作者: 随风dd
  • 本文链接: https://www.cnblogs.com/ddsuifeng/p/17176006.html
  • 关于博主: 评论和私信会在第一时间回复。或者直接私信我。
  • 版权声明: 本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
  • 声援博主: 如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。
  • 相关阅读:
    easyexcel同步下载简单使用
    Redis-服务器
    都2202年了,不会有人还不会发布npm包吧
    Java项目论文+PPT+源码等]基于javaweb的网上订餐管理系统|点餐餐饮餐厅
    C# 生成指定图片的缩略图
    408 | 【计网】第二章 物理层 回顾
    土豆清洗去皮机设计
    JAVAEE初阶相关内容第十一弹续集--多线程(进阶)之常见面试题汇总1
    牛客小白月赛65
    基于驱动框架编写驱动代码
  • 原文地址:https://www.cnblogs.com/ddsuifeng/p/17176006.html