首页 > 其他分享 >luffy_06days 短信++

luffy_06days 短信++

时间:2024-01-24 19:22:55浏览次数:26  
标签:git 06days get ++ self mobile code user luffy

昨日回顾

#1 Git的作用
1 对文件(代码)进行版本管理
2 完成 协同开发 项目,帮助程序员整合代码
    i)帮助开发者合并开发的代码
    ii)如果出现冲突代码的合并,会提示后提交合并代码的开发者,让其解决冲突
    
#2 Git简介
Git是分布式版本控制系统(在本地进行版本管理),控制的对象是开发的项目代码(文件)
# 3 git和svn区别
    
# 4 Git,GitHub,GitLab,Gitee
Git:是一种版本控制系统,是一个命令,是一种工具。

GitHub:是一个基于Git实现的在线代码托管仓库,包含一个网站界面,向互联网开放,公有仓库免费,部分私有仓库收费,全球最大的开源代码托管平台

GitLab:是一个基于Git实现的在线代码仓库托管软件,可以通过GitLab自己搭建一个类似于GitHub一样的系统,用在企业内部网络搭建Git私服,用于企业团队内部协作开发

Gitee:(码云) 是 OSCHINA 推出的代码托管平台,支持 Git 和 SVN,提供免费的私有仓库托管,面向互联网开发,分收费和付费,中国最大的开源代码托管平台


# 5 git 工作流程,如下图

# 6 常用命令
git add
git commit -m

# 7  扩展阅读
# git log 和git reflog的区别
git log 命令可以显示所有提交过的版本信息
如果感觉太繁琐,可以加上参数  --pretty=oneline,只会显示版本号和提交时的备注信息

git reflog 可以查看所有分支的所有操作记录(包括已经被删除的 commit 记录和 reset 的操作)


# 8 git reset --hard,--mix,--soft的区别
hard (硬)-> 全部删除,会彻底返回到回退前的版本状态,了无痕迹
mixed (中)-> 保留工作目录,文件回退到未commit的状态
soft (软)-> 保留工作目录、暂存区 ,文件会回退到未 add(未到暂存)的状态
总结:
soft是撤销commit的提交,但工作区未提交的更改还是保留;
mixed是撤销暂存区的提交,工作区的更改同样也保留;
而hard是把工作区、暂存区、commit到仓库的三个版本都回滚了

# 9 Git忽略文件
    .gitignore
    直接写文件夹
    直接写文件
    *.mp4
    !xx  
  
# 10  分支操作
#1.创建分支
git branch 分支名

#2.查看分支
git branch

#3.切换分支
git checkout 分支名

# 4.创建并切换到分支
git checkout -b 分支名

# 5.删除分支
git branch -d 分支名

# 6.查看远程分支(列出所有分支,包含远程)
git branch -a

# 7.合并分支
git merge 分支名
把dev分支合并到master分支:切换到master分支,执行合并dev分支的命令

# 8.删除远程分支
git push origin --delete lqz

# 9.新建远程分支
本地lqz分支建立完成
git push origin lqz 


# 11 dev和master分支合并

# 12 bug和master合并+dev和master合并---》可能会有冲突
    
# 13 远程仓库创建和提交代码

# 14 remote操作
    # 1)查看仓库已配置的远程源
    >: git remote
    >: git remote -v

    # 2)查看remote命令帮助文档
    >: git remote -h

    # 3)删除远程源
    >: git remote remove 源名
    eg: git remote remove origin

    # 4)添加远程源
    >: git remote add 源名 源地址
    >: git remote add orgin https://gitee.com/liuqingzheng/app01.git

    # 5)提交代码到远程源
    >: git push 源名 分支名

    # 6)克隆远程源
    >: git clone 远程源地址
    # 7) 拉取代码
    git pull origin master
    git fetch origin master # 拉取代码


# 15 ssh协议连接远程源
    -加密几种方式:
        1 编码:base64   urlencoded
        2 摘要算法: md5,sha1
        3 对称加密:aes
        4 非对称加密:des
    -本地生成公钥私钥
    -公钥配置在远程仓库
    -以后就可以使用ssh的免密操作

# 16 协同开发
    - 你是仓库创建者---》远程创建仓库为空
        -本地有仓库
        -本地没仓库
        
    -你是仓库创建者---》远程创建仓库不为空
        -本地仓库为空---》git clone下来,把代码复制到这个仓库中即可
        -本地仓库不为空---》git clone下来--需要以远程仓库为准--》把代码复制到这个仓库中即可,不要复制.git文件夹
        
        
   -你是开发者---》仓库创建者把你加为开发者--》你进你的账号---》就能看到这个项目
    -git clone 下来,pycharm打开
    -继续开发代码--》提交本地--》推到远程即可
    -出现冲突就解决冲突即可
    
    
# 17 冲突解决
    -多人在同一分支开发
    -分支合并
    
    -秘诀:少出冲突的原则是
        不停的拉取代码

# 18 线上分支合并
    提交pr:gitee
    提交mr:gitlab
        
# 19 为开源贡献代码

# 20 其他
    变基操作:rebase  多个记录合成一个,提交记录更简洁
    git pull 和git fetch
        1. 相同点
        首先在作用上他们的功能是大致相同的,都是起到了更新代码的作用。
        2. 不同点
        git pull 等同于 git fetch+git merge
        
        
# 21 pycharm使用git

# 21 gitlab  使用---》搭建是运维
    -地址:http://192.168.1.252/
    -超级管理员:root     lqz123456
    


# 补充:
    以后有前端项目   后端项目---》这俩项目,放一个仓库还是俩仓库?
        每个项目一个仓库
        
        之前每个项目都被git管理了, .git   .gitignore
        
        project
          .git
          .gitignore
          front
          backend

今日内容

# 回退到某个版本
    -git rest --hard  版本号
    -推送到远端
    git push origin master -f   # 慎用 ,你不要用
# 用户板块---》原型图---分析需要写哪些接口
    -多方式登录接口
    -短信登录接口
    -发送短信接口
    -短信注册接口
    -校验手机号是否注册接口

手机号是否存在

#### 视图类:
class UserMobile(ViewSet):
    @action(methods=['post'], detail=False, url_path='check_mobile')
    def mobile(self, request):
        try:
            mobile = request.data.get('mobile')
            User.objects.get(mobile=mobile)  # 能拿到说明手机号存在
            return APIResponse(msg='手机号存在')
        except Exception as e:
            raise APIException(detail='手机号不存在')
            
#### 路由
from .views import UserMobile
from rest_framework.routers import SimpleRouter

router = SimpleRouter()
# /api/v1/user/mobile/check_mobile/
router.register('mobile', UserMobile, 'mobile')

urlpatterns = [
]

### 访问:
url:    http://127.0.0.1:8000/api/v1/user/mobile/check_mobile/
请求方式:post请求
请求体:  {"mobile":"18953575221"}

多方式登录接口

 视图类

class UserLoginView(GenericViewSet):
    serializer_class = MulLoginSerializer

    # queryset = User.objects.all()  # 不需要写
    @action(methods=['POST'], detail=False)
    def mul_login(self, request):
        ser = self.get_serializer(data=request.data,context={'request':request})
        ser.is_valid(raise_exception=True)
        token = ser.context.get('token')
        username = ser.context.get('username')
        icon = ser.context.get('icon')
        return APIResponse(token=token, username=username, icon=icon)

序列化类

from rest_framework import serializers
from .models import User
import re
from rest_framework.exceptions import ValidationError, APIException
from rest_framework_simplejwt.tokens import RefreshToken
from django.conf import settings


# 这个序列化类 只用来做 反序列化的校验,其他不用
class MulLoginSerializer(serializers.ModelSerializer):
    # 会自动把 models.py 中写的 username 和password 映射过来
    # username = models.CharField(
    #     max_length=150,
    #     unique=True, # 唯一性校验,走到字段自己的校验规则,表示数据库中只能有一条---》会做校验---》去数据库查询有没有名字为lqz的记录-->数据库中有,字段自己规则就过不了了
    # )

    # 重写 username字段,去掉字段自己的规则
    username = serializers.CharField()

    # password=serializers.CharField
    class Meta:
        model = User
        fields = ['username', 'password']

    def validate(self, attrs):
        # 1 取出用户提交的用户名[用户名、手机、邮箱] 和密码
        # 2 去数据库校验
        user = self._get_user(attrs)
        # 3 校验通过,签发token
        token = self._get_token(user)
        # 4 放到context中
        self._set_context(token, user)
        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'^.+@.+$', 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(detail='用户名或密码错误')

    def _get_token(self, user):
        refresh = RefreshToken.for_user(user)
        # self.context['refresh'] = str(refresh)
        return str(refresh.access_token)

    def _set_context(self, token, user):
        request = self.context.get('request')
        # print(request.headers.get('Host'))
        self.context['token'] = token
        self.context['username'] = user.username
        # icon 缺了前面  http://127.0.0.1:8000/media/
        # 如果从request中取不出来服务端ip和端口
        # 把ip和端口配置在配置文件中
        # self.context['icon'] = request.META.get('HTTP_HOST')+'/media/'+str(user.icon)  # user.icon 文件对象
        self.context['icon'] = settings.BACKEND_URL + '/media/' + str(user.icon)  # user.icon 文件对象

路由

from .views import UserMobile, UserLoginView
from rest_framework.routers import SimpleRouter

router = SimpleRouter()
# /api/v1/user/mobile/check_mobile/
router.register('mobile', UserMobile, 'mobile')
# /api/v1/user/login/mul_login/
router.register('login', UserLoginView, 'login')

urlpatterns = [
]

urlpatterns += router.urls

腾讯云短信封装

# 项目中使用发送短信功能,借助于第三方
    -腾讯云短信(咱们)
    -阿里 大于短信
    -容联云短信
    
# 补充:短信轰炸


# 登录成功:https://console.cloud.tencent.com/smsv2

# 短信发送:https://cloud.tencent.com/document/product/382/55981
    API:api接口,请求地址,携带参数,返回某些格式
        -用起来比较麻烦
    sdk:使用某种语言对api接口进行封装---》
        -有sdk,优先用sdk,简单
        -下载sdk,导入,掉方法执行,传入参数即可
        
# 下载sdk
pip install tencentcloud-sdk-python

封装

# send_sms
    __init__.py
    settings.py
    sms.py

init.py

from .sms import get_code,common_send_sms

settings.py

SECRET_ID = ''
SECRET_KEY = ''

# 申请的短信应用 SDK AppID
APP_ID = ''

# 申请的短信模板ID,需要在短信控制台中申请
TEMPLATE_ID = ''

# 申请的签名,参数使用的是`签名内容`,而不是`签名ID`
SIGN = ""

sms.py

# 提供函数,给外部使用
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
from . import settings
# 1 生成随机数字验证码的函数
import random
import json
from rest_framework.exceptions import APIException


def get_code(count=4):
    code = ''
    for i in range(count):
        code += str(random.randint(0, 9))
    return code


# 2 发送短信函数
def common_send_sms(code, mobile):
    try:
        cred = credential.Credential(settings.SECRET_ID, settings.SECRET_KEY)
        httpProfile = HttpProfile()
        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
        client = sms_client.SmsClient(cred, "ap-guangzhou", clientProfile)
        req = models.SendSmsRequest()
        req.SmsSdkAppId = settings.APP_ID
        # 短信签名内容: 使用 UTF-8 编码,必须填写已审核通过的签名
        # 签名信息可前往 [国内短信](https://console.cloud.tencent.com/smsv2/csms-sign) 或 [国际/港澳台短信](https://console.cloud.tencent.com/smsv2/isms-sign) 的签名管理查看
        req.SignName = settings.SIGN
        # 模板 ID: 必须填写已审核通过的模板 ID
        # 模板 ID 可前往 [国内短信](https://console.cloud.tencent.com/smsv2/csms-template) 或 [国际/港澳台短信](https://console.cloud.tencent.com/smsv2/isms-template) 的正文模板管理查看
        req.TemplateId = settings.TEMPLATE_ID
        # 模板参数: 模板参数的个数需要与 TemplateId 对应模板的变量个数保持一致,,若无模板参数,则设置为空
        req.TemplateParamSet = [code]
        # 下发手机号码,采用 E.164 标准,+[国家或地区码][手机号]
        # 示例如:+8613711112222, 其中前面有一个+号 ,86为国家码,13711112222为手机号,最多不要超过200个手机号
        req.PhoneNumberSet = ["+86" + mobile]
        # 用户的 session 内容(无需要可忽略): 可以携带用户侧 ID 等上下文信息,server 会原样返回
        req.SessionContext = ""
        # 短信码号扩展号(无需要可忽略): 默认未开通,如需开通请联系 [腾讯云短信小助手]
        req.ExtendCode = ""
        # 国内短信无需填写该项;国际/港澳台短信已申请独立 SenderId 需要填写该字段,默认使用公共 SenderId,无需填写该字段。注:月度使用量达到指定量级可申请独立 SenderId 使用,详情请联系 [腾讯云短信小助手](https://cloud.tencent.com/document/product/382/3773#.E6.8A.80.E6.9C.AF.E4.BA.A4.E6.B5.81)。
        req.SenderId = ""
        resp = client.SendSms(req)
        # 输出json格式的字符串回包
        resp = json.loads(resp.to_json_string(indent=2))
        if resp.get('SendStatusSet')[0].get('Code') == 'Ok':
            return True
        else:
            return False

    except TencentCloudSDKException as err:
        raise APIException(detail=str(err))
    except Exception as e:
        raise APIException(detail=str(e))


if __name__ == '__main__':
    print(get_code())

发送短信接口

 

 # 发送短信接口
    @action(methods=['get'], detail=False, url_path='send_sms')
    def send(self, request):
        try:
            mobile = request.query_params['mobile']
            code = get_code()  # 生成验证码,要存一下  之前验证码放session中,现在放在缓存中
            cache.set('sms_code_%s' % mobile, code)  # 放在缓存中,以手机号做区分
            # res = common_send_sms(code, mobile) # 同步发送
            # if res:
            #     return APIResponse(msg='短信发送成功')
            # else:
            #     return APIResponse(code=101, msg='短信发送失败')
            # 异步发送短信---不用管是否成功---》如果不成功,用户在发一次即可
            t = Thread(target=common_send_sms, args=[code, mobile])
            t.start()
            return APIResponse(msg='短信已发送')

        except MultiValueDictKeyError as e:
            raise APIException(detail='手机号必须携带')
        except Exception as e:
            # print(type(e))
            raise APIException(detail=str(e))

短信登录功能

# 前端传入的数据  {mobile:1823433,code:8888}

视图类

class UserLoginView(GenericViewSet):
    @action(methods=['POST'], detail=False)
    def sms_login(self, request):
        return self._common_login(request)

    def get_serializer_class(self):
        if self.action == 'sms_login':
            return SmsLoginSerializer
        else:
            return super().get_serializer_class()

    def _common_login(self, request):
        ser = self.get_serializer(data=request.data, context={'request': request})
        ser.is_valid(raise_exception=True)
        token = ser.context.get('token')
        username = ser.context.get('username')
        icon = ser.context.get('icon')
        return APIResponse(token=token, username=username, icon=icon)

序列化类

class CommonLoginSerializer(serializers.Serializer):
    def validate(self, attrs):
        user = self._get_user(attrs)
        token = self._get_token(user)
        self._set_context(token, user)
        return attrs

    def _get_user(self, attrs):
        raise Exception('这个方法必须被重写')

    def _get_token(self, user):
        refresh = RefreshToken.for_user(user)
        # self.context['refresh'] = str(refresh)
        return str(refresh.access_token)

    def _set_context(self, token, user):
        request = self.context.get('request')
        # print(request.headers.get('Host'))
        self.context['token'] = token
        self.context['username'] = user.username
        # icon 缺了前面  http://127.0.0.1:8000/media/
        # 如果从request中取不出来服务端ip和端口
        # 把ip和端口配置在配置文件中
        # self.context['icon'] = request.META.get('HTTP_HOST')+'/media/'+str(user.icon)  # user.icon 文件对象

        self.context['icon'] = settings.BACKEND_URL + '/media/' + str(user.icon)  # user.icon 文件对象

# 只做 反序列化的校验,其他不用
class SmsLoginSerializer(CommonLoginSerializer):
    mobile = serializers.CharField()
    code = serializers.CharField()

    def _get_user(self, attrs):
        # 1 取出验证码
        code = attrs.get('code')
        mobile = attrs.get('mobile')
        old_code = cache.get('sms_code_%s' % mobile)
        # 2 校验验证码是否正确,不正确,抛异常
        # 留了个后门,为了测试方便,不再真正发送验证码
        if code == old_code or (settings.DEBUG and code == '8888'):
            # 3 拿着手机号查询用户,查不到用户,抛异常
            user = User.objects.filter(mobile=mobile).first()
            if user:
                return user
                # 4 返回用户即可
            else:
                raise APIException('用户不存在')

        else:
            raise APIException('验证码错误')

短信注册功能

# 前端传入的 {mobile,code,password}---->User表中字段:username必填,自动生成fake 我们让手机号做用户名

视图类

class UserRegister(GenericViewSet):
    serializer_class = RegisterSerializer

    # @action(methods=['POST'], detail=False)
    # def register(self, request):
    def create(self, request):
        ser = self.get_serializer(data=request.data)
        ser.is_valid(raise_exception=True)
        ser.save() # 走序列化类的create方法
        return APIResponse(msg='恭喜您,注册成功')

序列化类

class RegisterSerializer(serializers.ModelSerializer):
    code=serializers.CharField() # 因为code不是表的字段,所以必须重写
    class Meta:
        model = User
        fields = ['mobile', 'code', 'password']

    def validate(self, attrs):
        # 1 校验验证码是否正确
        code = attrs.pop('code')
        mobile = attrs.get('mobile')
        old_code = cache.get('sms_code_%s' % mobile)
        # 2 注册前的数据准备(用户名)
        if code == old_code or (settings.DEBUG and code == '6666'):
            # 2.1 code pop 出来 上面做了
            # 2.2 把用户名放入
            attrs['username'] = mobile
        else:
            raise APIException('验证码错误')
        # 3 返回校验过后的数据
        return attrs

    def create(self, validated_data):
        # validated_data {mobile,password,username}
        user = User.objects.create_user(**validated_data)
        return user

路由

#/api/v1/user/register/
router.register('register', UserRegister, 'register')

 

标签:git,06days,get,++,self,mobile,code,user,luffy
From: https://www.cnblogs.com/wzh366/p/17985677

相关文章

  • C++ STL Template Traits 技术
    C++的traits技术,是一种约定俗称的技术方案,用来为同一类数据(包括自定义数据类型和内置数据类型)提供统一的类型名(traits),这样可以统一的操作函数,例如advance(),swap(),encode()/decode()等。问题描述首先来看traits技术可以解决什么问题,我们拥有自定义类型Foo,Bar,以及编译......
  • 【C++入门到精通】C++入门 —— 深浅拷贝函数
     目录拷贝函数浅拷贝拷贝构造函数深拷贝拷贝构造函数总结 前言Linux专栏链接)大家可以关注一下,后面我会一点一点的更新的。大家坐稳扶好,要开车了!!!拷贝函数拷贝构造详细介绍)        是C++中的一个特殊成员函数,用于创建对象的副本。它的作用是通过使用已有对象的属性值来初始......
  • 【C++入门到精通】C++入门 —— 深浅拷贝函数
     目录拷贝函数浅拷贝拷贝构造函数深拷贝拷贝构造函数总结 前言Linux专栏链接)大家可以关注一下,后面我会一点一点的更新的。大家坐稳扶好,要开车了!!!拷贝函数拷贝构造详细介绍)        是C++中的一个特殊成员函数,用于创建对象的副本。它的作用是通过使用已有对象的属性值来初始......
  • Java和C++的区别:传闻这个问题能分辨你是不是科班出生?
    大家好,欢迎来到程序视点!我是小二哥。今天听到一个面试的小伙伴分享了他的面试经历,说面试官第一个问题是:Java语言和C++语言的区别有哪些?坊间流传,早些年间这个问题能区分一个Java程序员是不是科班出身!小伙伴怎么认为呢?缘由由于Java本来就是从C++衍生出来的,而且Java语言......
  • C++缺省参数
    缺省参数什么是缺省参数呢?简单来说,就是函数的参数可以给一个默认值,如果不给这个函数传递参数的时候那么改参数就是默认值,否则参数就是你指定的参数缺省参数分为全缺省和半缺省全缺省参数:所有的参数都有默认值voidfunc(inta=10,intb=20,intc=30){cou......
  • 图论---可视区域获取(C++)
    1.开源库获取   地址:http://en.wikipedia.org/wiki/Visibility_graph2.使用使用处包含头文件 #include"visilibity.hpp"即可,以下面在Qt中使用为例:1/*2=========AVisiLibityExampleProgram=========3Thisprogramprovidesatextinterfacewhic......
  • c++学习由浅入深刷题指南
    新手村任何一个伟大的目标,都有一个微不足道的开始。洛谷的第一个任务勇敢的迈出第一步,了解下语言和洛谷。跟着书本和老师走,不会难的。P1000P1001P1421P1425顺序与分支计算机的智能性开始得以体现,因为计算机能够根据不同的条件选择了。P1422P1085P1089P1909循环!......
  • C++ 项目结构
    1.C++项目结构C++项目包含几千个文件,当构建项目时,需要选择编译哪些文件,选择哪种工具编译这些文件组织称可执行文件1.1编译计算机处理器只能执行底层二进制指令,编译器需要将C++源码转换成处理器能执行的指令集。编译器配置的内存称为栈帧(Stackframe),配置内存传递数......
  • notepad++ compare plus/compare plugin 64bit
    *[Releases·pnedev/comparePlus](https://github.com/pnedev/comparePlus/releases)https://objects.githubusercontent.com/github-production-release-asset-2e65be/50095301/5d0a2666-67f4-4971-9354-12339a75dd1f?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credent......
  • 【干货】VS Code中配置C/C++运行环境
    1、安装MinGW-w64有个很重要的工具:MinGW-w64,里面包含了在windows上编译调试C++代码所需要的所有环境(以及一些其他的小工具包,例如linux风格的命令ls,将这个包解压缩后的路径添加到系统环境变量PATH中就可以用了)。他的具体的发布和下载位置:Releases·skeeto/w64devkit(github.co......