Django项目--路飞学城项目04


主要内容

# 登录注册功能
# 接口分析
    -1 账号密码登录
        -多方式登录接口
        
    -校验手机号是否存在接口 (短信登录和注册,都需要校验手机号是否存在)
        
    -2 短信登录    	
        -发送短信接口
            -阿里短信
            -腾讯短信平台(以它为例)
    	-短信登录接口
        
    -3 短信注册
    	-短信注册接口

1 登录注册页面(前端)

# 要点:
    1.以模态框的形式弹出 登录与注册页面  (页面绝对定位 + 覆盖页面的 css样式)
    2.点击关闭按钮,存在子组件向父组件通信 (通过自定义事件,子组件触发父组件的事件执行)






1.1 Login.vue






1.2 Register.vue






1.3 Header.vue






2 多方式登录接口

# 使用用户名,邮箱,手机号+密码登录
    {username:lqz/132834355/33@qq.com,password:12345}
class LoginView(ViewSet):
    def login(self, request):
        # 逻辑写在序列化类中
        # 1.用if判断的形式,返回数据
        # if ser.is_valid():
        #     token = ser.context.get('token')
        #     username = ser.context.get('user').username
        #     return APIResponse(msg='登录成功', token=token, username=username)
        # else:
        #     # return APIResponse(code=101, msg=ser.errors)
        #     return APIResponse(code=101, msg='用户名或密码错误')
        
        # 2.以序列化器校验 抛异常的形式 返回 (更简洁和常用)
        ser.is_valid(raise_exception=True)
        token = ser.context.get('token')
        username = ser.context.get('user').username
        return APIResponse(msg='登录成功', token=token, username=username)
        
                
# 序列化类
# 用来: 反序列化,验证前端传入的字段是否合法
class LoginSerializer(serializers.ModelSerializer):
    # 坑
    '''
    username:由于映射了User表的Username,自己有规则,unique=True
    username字段自己的校验,会走unique,会去数据库查是否有这个用户,如果有,直接抛异常
    故重写这个字段,不设置规则
    '''
    username = serializers.CharField(max_length=16, min_length=3)

    class Meta:
        model = models.User
        fields = ['username', 'password']

    def validate(self, attrs):
        '''
        1 根据用户名(手机号,邮箱)获取用户
        2 如果用户存在,签发token
        3 把token放到序列化类的对象中
        '''
        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')
        # 多种登录方式,正则匹配,如果是手机号根据手机号查。。。
        # ^(13[0-9]|14[01456879]|15[0-35-9]|16[2567]|17[0-8]|18[0-9]|19[0-35-9])\d{8}$
        if re.match(r'^1[3-9][0-9]{9}$', username):
            user=models.User.objects.filter(mobile=username).first()
        # elif re.match(r'[A-Za-z0-9\u4e00-\u9fa5]+@[a-zA-Z0-9_-]+(\.[a-zA-Z0-9_-]+)+$',username):
        elif re.match(r'^.+@.+$',username):
            user = models.User.objects.filter(email=username).first()
        else:
            user = models.User.objects.filter(username=username).first()
        if user and user.check_password(password):
            return user
        else:
            raise ValidationError('用户名或密码错误')

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

3 手机号是否存在接口

class MobileView(ViewSet):
    # api/v1/user/mobile/?mobile=12334454
    # url_path的作用,自动生成的url路径,默认为空,则以函数名为路径
    # @action(methods=['GET'], detail=False,url_path='mobile') 
    # def check_mobile(self, request):
    
    @action(methods=['GET'], detail=False)
    def mobile(self, request):
        mobile = request.query_params.get('mobile')
        try:
            models.User.objects.get(mobile=mobile)
        except Exception:
            raise APIException('手机号不存在')
        return APIResponse(is_exisit=True)

4 腾讯云短信开发

# 申请公众号
    -一个邮箱只能注册一个(公众号和小程序)
    -https://mp.weixin.qq.com/ 小程序和公众号放到一起了
    -按照流程一步步注册
    -登录,进入到账号详情

# 集成腾讯短信服务---》按照文档操作
# https://cloud.tencent.com/product/sms
# 注册--》登录---》短信服务

# https://console.cloud.tencent.com/smsv2/csms-template
# 使用步骤
    1.创建短信签名
    2.创建短信正文模板
      等待审核
    3.创建应用
    4.发送短信
    
# 刚申请,送100条
    
    
# API和SDK的区别
    -API:指一堆接口,http/https接口---》写起来比较麻烦
    -sdk:使用不同语言基于这些接口封装的代码,java,python,nodejs版本sdk
    -python的sdk:V2版本,V3版本
    	-咱们用V2:qcloudsms_py,只用来发短信
        -https://cloud.tencent.com/document/product/382/11672
        
        -新版本V3:tencentcloud-sdk-python,不仅包含了短信功能,还包含了其他腾讯云功能:对象存储...
        -https://cloud.tencent.com/document/product/382/56059
        
    -第三方服务肯定会有api,sdk看公司情况
    	-支付宝支付-->有api,但是没有sdk(第三方

4.1 腾讯云v2.0 单发短信

from qcloudsms_py import SmsSingleSender
from qcloudsms_py.httpclient import HTTPError

# 短信应用 SDK AppID
appid = 1400000000  # SDK AppID 以1400开头
# 短信应用 SDK AppKey
appkey = "fd972f6d5a15add46de47b50b8dbe930"

# 需要发送短信的手机号码
phone_numbers = ["18953670000", ]
# 短信模板ID,需要在短信控制台中申请
template_id = 1049981  # NOTE: 这里的模板 ID`7839` 只是示例,真实的模板 ID 需要在短信控制台中申请
# 签名
sms_sign = "小猿取经"  # NOTE: 签名参数使用的是`签名内容`,而不是`签名ID`。这里的签名"腾讯云"只是示例,真实的签名需要在短信控制台中申请

ssender = SmsSingleSender(appid, appkey)
params = ["5678", '3']  # 当模板没有参数时,`params = []`
try:
    result = ssender.send_with_param(86, phone_numbers[0],
                                     template_id, params, sign=sms_sign, extend="", ext="")
except HTTPError as e:
    print(e)
except Exception as e:
    print(e)
print(result)

4.2 腾讯云v3.0 单发短信

# -*- coding: utf-8 -*-
from tencentcloud.common import credential
from tencentcloud.common.exception.tencent_cloud_sdk_exception import TencentCloudSDKException
# 导入对应产品模块的client models。
from tencentcloud.sms.v20210111 import sms_client, models

# 导入可选配置类
from tencentcloud.common.profile.client_profile import ClientProfile
from tencentcloud.common.profile.http_profile import HttpProfile
try:
    # 必要步骤:
    # 实例化一个认证对象,入参需要传入腾讯云账户密钥对secretId,secretKey。
    # 这里采用的是从环境变量读取的方式,需要在环境变量中先设置这两个值。
    # 你也可以直接在代码中写死密钥对,但是小心不要将代码复制、上传或者分享给他人,
    # 以免泄露密钥对危及你的财产安全。
    # CAM密匙查询: https://console.cloud.tencent.com/cam/capi
    cred = credential.Credential("密钥id", "密钥key")
    # cred = credential.Credential(
    #     os.environ.get(""),
    #     os.environ.get("")
    # )

    # 实例化一个http选项,可选的,没有特殊需求可以跳过。
    httpProfile = HttpProfile()
    # 如果需要指定proxy访问接口,可以按照如下方式初始化hp
    # httpProfile = HttpProfile(proxy="http://用户名:密码@代理IP:代理端口")
    httpProfile.reqMethod = "POST"  # post请求(默认为post请求)
    httpProfile.reqTimeout = 30    # 请求超时时间,单位为秒(默认60秒)
    httpProfile.endpoint = "sms.tencentcloudapi.com"  # 指定接入地域域名(默认就近接入)

    # 非必要步骤:
    # 实例化一个客户端配置对象,可以指定超时时间等配置
    clientProfile = ClientProfile()
    clientProfile.signMethod = "TC3-HMAC-SHA256"  # 指定签名算法
    clientProfile.language = "en-US"
    clientProfile.httpProfile = httpProfile

    # 实例化要请求产品(以sms为例)的client对象
    # 第二个参数是地域信息,可以直接填写字符串ap-guangzhou,或者引用预设的常量
    client = sms_client.SmsClient(cred, "ap-guangzhou", clientProfile)

    # 实例化一个请求对象,根据调用的接口和实际情况,可以进一步设置请求参数
    # 你可以直接查询SDK源码确定SendSmsRequest有哪些属性可以设置
    # 属性可能是基本类型,也可能引用了另一个数据结构
    # 推荐使用IDE进行开发,可以方便的跳转查阅各个接口和数据结构的文档说明
    req = models.SendSmsRequest()

    # 基本类型的设置:
    # SDK采用的是指针风格指定参数,即使对于基本类型你也需要用指针来对参数赋值。
    # SDK提供对基本类型的指针引用封装函数
    # 帮助链接:
    # 短信控制台: https://console.cloud.tencent.com/smsv2
    # sms helper: https://cloud.tencent.com/document/product/382/3773

    # 短信应用ID: 短信SdkAppId在 [短信控制台] 添加应用后生成的实际SdkAppId,示例如1400006666
    req.SmsSdkAppId = "1400634441"
    # 短信签名内容: 使用 UTF-8 编码,必须填写已审核通过的签名,签名信息可登录 [短信控制台] 查看
    req.SignName = "靡克世界"
    # 短信码号扩展号: 默认未开通,如需开通请联系 [sms helper]
    req.ExtendCode = ""
    # 用户的 session 内容: 可以携带用户侧 ID 等上下文信息,server 会原样返回
    req.SessionContext = "xxx"
    # 国际/港澳台短信 senderid: 国内短信填空,默认未开通,如需开通请联系 [sms helper]
    req.SenderId = ""
    # 下发手机号码,采用 E.164 标准,+[国家或地区码][手机号]
    # 示例如:+8613711112222, 其中前面有一个+号 ,86为国家码,13711112222为手机号,最多不要超过200个手机号
    req.PhoneNumberSet = ["+8618280490000"]
    # 模板 ID: 必须填写已审核通过的模板 ID。模板ID可登录 [短信控制台] 查看
    req.TemplateId = "1306372"
    # 模板参数: 若无模板参数,则设置为空
    req.TemplateParamSet = ["666666"]


    # 通过client对象调用DescribeInstances方法发起请求。注意请求方法名与请求对象是对应的。
    # 返回的resp是一个DescribeInstancesResponse类的实例,与请求对象对应。
    resp = client.SendSms(req)

    # 输出json格式的字符串回包
    print(resp.to_json_string(indent=2))

except TencentCloudSDKException as err:
    print(err)

相关