首页 > 其他分享 >路飞之登录注册接口

路飞之登录注册接口

时间:2023-03-03 21:34:48浏览次数:30  
标签:username 短信 登录 接口 路飞 token user 序列化

目录

路飞之登录注册接口

登录接口

接口分析可知,登录注册接口需要五个接口,分别是校验手机号是否存在的接口多方式登录接口(用户名/手机号/邮箱+密码),发送手机验证码接口(借助于第三方短信平台)、短信登录接口注册接口

  1. 总路由分发user路由

    # 总路由
    path('api/v1/user/',include('user.urls'))
    
    # 路由
    from rest_framework.routers import SimpleRouter
    from .views import UserView
    
    router = SimpleRouter()
    # 访问 http://127.0.0.1:8000/api/v1/user/userinfo/send_msg   ---->get 发送短信
    router.register('userinfo',UserView , 'userinfo')
    
    urlpatterns = [
    ]
    urlpatterns += router.urls
    
  2. 视图层

    from rest_framework.viewsets import GenericViewSet
    from rest_framework.decorators import action
    from user.models import User
    from utils.common_response import APIResponse
    
    # # 第一版本
    # class UserView(GenericViewSet):
    #     @action(methods=['GET'],detail=False)
    #     def send_msg(self,request,*args,**kwargs):  # 保证这个接口的安全(短信轰炸机--》解析出了好多网站的发送短信接口,用多线程)
    #         mobile = request.query_params['mobile']
    #         if mobile:
    #             user=User.objects.filter(mobile=mobile).first()
    #             if user:
    #                 return APIResponse(code=100,msg='手机号存在',exist=True)
    #             else:
    #                 return APIResponse(code=100,msg='手机号不存在',exist=True)
    #         else:
    #             return APIResponse(code=888,msg='手机号必填')
    
    # 进阶版本
    class UserView(GenericViewSet):
        @action(methods=['GET'],detail=False)
        def send_msg(self,request,*args,**kwargs):  # 保证这个接口的安全(短信轰炸机--》解析出了好多网站的发送短信接口,用多线程)
            try:
                # 从地址栏中取出手机号  query_params :queryDict
                mobile = request.query_params['mobile']  # 取不到值会报错---全局异常
                User.objects.get(mobile=mobile)
                # get 取不到值返回none
            except Exception as e:
                raise e
                # return APIResponse(code=888,msg='手机号必填')
            return APIResponse(msg='手机号存在')
    

视图层

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

多方式登录接口

视图类

from utils.common_response import APIResponse
from .serializer import UserLoginSerializer
class UserView(GenericViewSet):
    @action(methods=['POST'], detail=False)
    def login_mul(self, request, *args, **kwargs):
        """
        把这个逻辑放在序列化类中
        1.取出前端传入的用户名和密码
        2.通过用户名和密码去数据库查询用户
        3.如果能查到,签发token
        4.返回给前端登录成功
        """
        # 实例化 序列化类对象时,可以传入context 字典     context 是 视图类和序列化类沟通的桥梁
        # 序列化类全局钩子,放入的
        # 有了序列化类对象,通过  对象.context 就可以拿到值
        ser = self.get_serializer(data=request.data)
        ser.is_valid(raise_exception=True)  # 执行这句话,会走字段自己的校验,局部钩子,全局钩子
        token = ser.context.get('token')
        username = ser.context.get('username')
        return APIResponse(token=token, username=username)  # {code:100,msg:成功,token:aasdfa,username:kimi}

序列化类

import re
from rest_framework import serializers
from .models import User
from rest_framework.exceptions import APIException
from rest_framework_jwt.settings import api_settings
jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER
jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER

# 这个序列化类用来校验字段---不做序列化,也不做反序列化
class UserLoginSerializer(serializers.ModelSerializer):
    """ 重写username,因为序列化就是校验字段是唯一性,重写把原来的规则去掉"""
    username = serializers.CharField()

    class Meta:
        model = User
        # username映射过来,是唯一的,字段自己的校验就过不了,所有要重写这个字段
        fields = ['username', 'password']  # 这个序列化类用来校验字段---不做序列化,也不做反序列化

    """
    把这个逻辑放在序列化类中
    1.取出前端传入的用户名和密码
    2.通过用户名和密码去数据库查询用户
    3.如果能查到,签发token
    4.返回给前端登录成功
    """

    # 全局钩子
    def validate(self, attrs):
        """attrs 是前端传入的数据,经过 字段自己校验和局部钩子校验过后的数据   {username:kimi,password:123} """
        user = self._get_user(attrs)
        token = self._get_token(user)
        self.context['token'] = token
        self.context['username'] = user.username
        return attrs

    # 在类内部,隐藏属性和方法, __ 开头
    # 公司里约定俗成,不用 __ ,使用 _ ,表示不想给外部用,但是实在想用,根据名字直接用
    def _get_user(self, attrs):
        username = attrs.get('username')
        password = attrs.get('password')
        # 校验三种类型
        if re.match(r'^1[3-9][0-9]{9}$', username):
            user = User.objects.filter(mobile=username).first()
        elif re.match(r'^[a-zA-Z0-9_.-]+@[a-zA-Z0-9-]+(\\.[a-zA-Z0-9-]+)*\.[a-zA-Z0-9]{2,6}$', username):
            user = User.objects.filter(email=username).first()
        else:
            user = User.objects.filter(username=username).first()
        if user and user.check_password(password):
            return user
        else:
            # 用户不存在或密码错误   这里的代码,还是在全局钩子中执行,全局钩子校验失败,要抛异常,所以在这抛异常
            raise APIException('用户名不存在或者密码错误')

    def _get_token(self, user):
        payload = jwt_payload_handler(user)
        token = jwt_encode_handler(payload)
        return token

腾讯云短信申请

# 发送短信接口,借助于第三方短信平台,收费的
	-腾讯云短信
    -阿里 大于短信
    
# 申请微信公众号

# 使用腾讯短信
    1.https://cloud.tencent.com,微信扫码登录
    2.搜索短信:https://console.cloud.tencent.com/smsv2
    3.创建短信签名:公众号注册,提交等待审核
	4.创建短信正文模版
	5.等待审核
	6.发送短信
    	python---短信
        
        
  # API SDK
	 API: 咱们学习过的API接口,写起来比较麻烦,自己分析接口
      SDK:集成开发工具包,分语言,java,python,go
    	  使用python 对api进行封装成包
           以后我们只需要,安装包,导入包,包名.发送短信,传入参数,就可以发送了
    
     只要官方提供sdk,优先用sdk
		 pip install tencentcloud-sdk-python

image

补充

# https://gitee.com/aeasringnar/django-RESTfulAPI/tree/master
# https://gitee.com/aeasringnar

标签:username,短信,登录,接口,路飞,token,user,序列化
From: https://www.cnblogs.com/zhanglanhua/p/17177038.html

相关文章