路飞项目---day07(为开源项目贡献代码,pycharm使用git,登录注册功能分析,及手机号是否存在及登录接口,腾讯云短信申请)

昨日回顾

# GIt内容大回顾

# 1 版本管理软件 :git,svn
	-代码合并
	-代码版本管理
	-协同开发,合并代码
# 2 git 跟 svn 区别
# 3 git 安装:相应平台软件,下载完成,一路下一步----》命令:git

# 4 git ,gitlab,gitee,github,bitbucket

# 5 git 工作流程
	-工作区
    -暂存区
    -版本库
    -远程仓库
    
    
# 6 git 常用命令
	-git init 名字   # .git 隐藏
    -git status
    -git add
    -git commit -m
    -git reset --hard 版本号
    -git log
    -git reflog
    
    -设置用户名(全局和局部)
    	git config --global user.name '用户名'
# 7 git 忽略文件
		.gitignore
    
    
    
# 8 分支管理
	-查看:git branch
    -git branch dev
    -git checkout dev
    -git branch -d dev
    -合并分支:git merge dev
    
# 9 远程仓库(gitee)
	-远程:创建仓库,空仓库
    -本地:
    	git init
        git add 
        git commit 
        # 添加远程仓库
        git remote add origin 地址(ssh/http)
        # 删除远程仓库
        git remote remove origin
        # 查看远程仓库
        git remote
        
        git push origin master  # 需要输入用户名密码
        git pull origin master  # 每次提交代码之前先拉
        
# 10 git clone 地址
	-你是开发者,项目已经有了,你需要克隆下来
    git clone 开源项目 # 没有任何阻碍
    
# 10 ssh操作远程仓库
	-公钥私钥----》
    -公钥配置在gitee上,以后使用ssh推送代码,就不需要验证
    -git remote add origin 地址(ssh)
    
    
# 11  冲突(面试)
	-多人在同一分支开发
    -分支合并
    
# 12 线上分支合并
	-提交pr
    
    
# 13 远程仓库回滚(忘掉)


    
    
# 记住的
	git add
    git commit -m
    git pull origin dev
    git push origin dev

今日内容

1 为开源项目贡献代码

# github,gitee 看到好的开源项目,  发现有bug,为他增加新功能---》你加入了代码---》想合并进开源项目,如何做

# 步骤:
	1 先fork开源项目--》复制这个项目到我的远程仓库中
	2 clone下来,改代码,一路提交到我的远程仓库中
	3 提交pr,等作者同意

先fork开源项目,到我的远程仓库中
image
clone下来,改代码,一路提交到我的远程仓库中 提交pr,等作者同意
image
.
.
.
.
.

2 pycharm使用git

# 只要用命令操作的,都可以点击完成

2.1 先配置pycharm使用git

提交所有变化文件的操作
image
.
提交一个文件操作
image
.
确认操作,也是如果只点击文件,就是确认一个文件,
如果点击文件夹,就是确认文件下所有的变化
image
.
双击一下文件,就可以看到,版本变化,加个注释,点击确认
image
.
拉去最新代码与自己代码合并
image
.
本地仓库代码推远程仓库
image
.
点勾,可以直接跳过add 并且再点commit and push
就可以直接推到远程仓库去了
image
.
如果git的路径没有添加到环境变量,这里就需要
选择到 bin/git.exe 配置好git安装路径
image
.
.
右下角的分支操作按钮,点击想要切换到的分支,checkout ,就切换过去了
所有本地与远程的分支操作,都在左下角
image
.
.
新增 删除 修改 远程仓库地址的名字
image
.
代码的对比,能看到每次版本修改的地方
image
image
还可以让历史版本与当前版本作对比
image
.
查看用户提交的代码记录
image
.
.
使用pycharm快捷从git上克隆项目代码
image
image
.
.
.

3 登录注册功能分析

# 接口分析
	5 校验手机号是否存在的接口
	1 多方式登录接口:用户名/手机号/邮箱 +密码都可以登录

	2 发送手机验证码接口   (借助于第三方短信平台)
	3 短信登录接口
	4 注册接口

.
.
.
.
.

4 手机号是否存在接口

urls.py 代码

from rest_framework.routers import SimpleRouter
from . import views

router = SimpleRouter()
# http://127.0.0.1:8000/api/v1/user/userinfo/send_sms/  get 发送短信
router.register('userinfo',views.UserView,'userinfo')

urlpatterns = [

]
urlpatterns += router.urls

.
.
.
views.py

# 老版的
from rest_framework.viewsets import GenericViewSet
from rest_framework.decorators import action
from luffy_api.apps.user.models import User

# 老版本代码,感觉老版方便
class UserView(GenericViewSet):

    @action(methods=['GET'], detail=False)
    def send_sms(self, request, *args, **kwargs):
        # 从地址栏中取出手机号
        mobile = request.query_params.get('mobile')
        if mobile:
            user_obj = User.objects.filter(mobile=mobile).first()
            if user_obj:
                return APIResponse(code=101, msg='手机号存在', exist=True)
            else:
                return APIResponse(code=101, msg='手机号不存在', exist=False)
        else:
            return APIResponse(code=999, msg='手机号必填')


------------------------------------------
------------------------------------------

# 新版的 利用全局异常处理
class UserView(GenericViewSet):
    @action(methods=['GET'], detail=False)
    def send_sms(self, request, *args, **kwargs):
        try:
            # 从地址栏中取出手机号  query_params :queryDict
            mobile = request.query_params['mobile']
            mobile = request.query_params.get('mobile')
            User.objects.get(mobile=mobile)
        except Exception as e:
            raise e
            # return APIResponse(code=777,msg='手机号不存在')
        return APIResponse(msg='手机号存在')


# 保证这个接口的安全(短信轰炸机--》解析出了好多网站的发送短信接口,用多线程)

.
.

4.2 视图函数模版

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

.
.
.
.
.
.
.

5 多方式登录接口

# 可以任意使用  用户名,手机号,邮箱其中的一个 + 密码登录

# post--{username:用户名/手机号/邮箱,password:123}

# 由于用户输入的可能是用户名/手机号/邮箱,所以要先根据用户输入的值,
# 决定去User表里面是查用户名,还是手机号,还是邮箱

# 需要用正则去匹配一下

.
.
.
.

5.1 视图类

# 手机号是否存在接口
from rest_framework.viewsets import GenericViewSet
from rest_framework.decorators import action
from luffy_api.apps.user.models import User
from rest_framework.exceptions import APIException

# 老版本代码,校验手机号码是否存在,感觉老版方便
# class UserView(GenericViewSet):
#
#     @action(methods=['GET'], detail=False)
#     def send_sms(self, request, *args, **kwargs):
#         # 从地址栏中取出手机号
#         mobile = request.query_params.get('mobile')
#         if mobile:
#             user_obj = User.objects.filter(mobile=mobile).first()
#             if user_obj:
#                 return APIResponse(code=101, msg='手机号存在', exist=True)
#             else:
#                 return APIResponse(code=101, msg='手机号不存在', exist=False)
#         else:
#             return APIResponse(code=999, msg='手机号必填')



from luffy_api.apps.user.serializer import UserLoginSerializer

# 新版本的代码
class UserView(GenericViewSet):
    serializer_class = UserLoginSerializer
    queryset = User.objects.all().filter(is_active=True)

    # 校验手机号是否存在
    @action(methods=['GET'], detail=False)
    def send_sms(self, request, *args, **kwargs):
        # 从地址栏中取出手机号  query_params :queryDict
        mobile = request.query_params.get('mobile')
        if mobile:
            # 有且只有一条,取不到会报错,变成django异常,会被全局捕获到
            user_obj = User.objects.get(mobile=mobile)
            return APIResponse(code=101, msg='手机号存在', exist=True)
        else:
            # 因为做了全局异常处理,所以主动抛异常也可以
            # return APIResponse(code=999, msg='手机号必填')
            raise APIException('手机号必填')


    # 校验用户名与密码是否正确,如果正确返回token与用户名
    @action(methods=['post'], detail=False)
    def login_multiple(self, request, *args, **kwargs):
        # 1 取出前端传入的用户名/手机号/邮箱 和密码
        # 2 通过用户名和密码去数据库查询用户
        # 3 如果能查到签发token
        # 4 返回给前端 登录成功
        ser = self.get_serializer(data=request.data)
        ser.is_valid(raise_exception=True)  # 走这句话,就会先执行字段自己的校验,然后局部钩子,全局钩子
        # is_valid()方法里面,raise_exception参数默认是False,函数正常返回布尔值,
        # 如果传raise_exception=True 校验过程发生异常后
        # 被is_valid里面的try接收到后,还会被主动抛异常的代码把异常信息再抛出去,一旦主动抛异常了,下面的代码就不会再走了

        # 在执行is_valid里面的全局钩子的时候,往ser.context对应的字典里面添加了数据
        # 所以context是视图类与序列化类沟通的桥梁,先通过序列化的对象.context['xx']=yy
        # 再在视图类函数里面,通过序列化的对象.context.get('xx') 拿到放进去的yy
        token = ser.context.get('token')
        username = ser.context.get('username')
        return APIResponse(token=token, username=username)


# 代码不多,逻辑有点多,校验用户名与密码的逻辑放到了序列化类里面去了

.
.
.
.

5.2 序列化类

# 先下载jwt模块
pip install --index-url http://pypi.douban.com/simple/ djangorestframework-jwt --trusted-host pypi.douban.com

from luffy_api.apps.user.models import User
from rest_framework import serializers
import re
from rest_framework.exceptions import APIException
import rest_framework_jwt
from rest_framework_jwt.settings import api_settings

jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER
jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER

from django.db.models import Q


# 这个序列化类用来校验字段-------不用来序列化------也不用来做反序列化
class UserLoginSerializer(serializers.ModelSerializer):
    class Meta:
        model = User
        fields = ['username', 'password']
        # 由于从User模型表里映射过来的username字段有unique唯一的限制条件
        # 所以序列化类里面该username字段校验,就也具有对唯一性的校验
        # 当输入正确的用户名,走is_valid方法,经过序列化类字段自己的校验时,发现该用户名与数据里的用户名一样
        # 就判断该用户名不具有唯一性,字段自己的校验就过不了,就直接抛异常了
        # 所以要在序列化类里面重写username字段,把原来表模型里面的校验规则去掉!!!

    username = serializers.CharField()

    # 执行全局钩子函数
    def validate(self, attrs):
        # 1 取出前端传入的用户名/手机号/邮箱 和密码
        # 2 通过用户名和密码去数据库查询用户
        # 3 如果能查到签发token
        # 4 返回给前端 登录成功
        # attrs是前端传入的数据,经过字段自己校验,和局部钩子校验过后的数据
        # 字段自己的校验是用fields将模型表对应的字段映射过来的,进行的校验
        user = self._get_user(attrs)
        token = self._get_token(user)
        # 把用户名与token放到ser的context字典中去,方便在视图类里面,通过字典再拿到放进去的值!
        self.context['token'] = token  # context是序列化类的基类Field里面的方法伪装成属性,返回值是字典
        self.context['username'] = user.username

        # 此处也可以不用context方法,直接给对象赋值,
        # 在视图类里直接通过 ser.token 拿对应的token值,但是该方法容易造成数据的污染,
        # 因为假如序列化类里面又定义了一个变量叫token,就容易把该token的值给顶掉了
        # self.token = token
        # self.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()

        # user = User.objects.filter(Q(username=username) | Q(email=username) | Q(mobile=username)).first()
        # 上面的正则匹配也可以不用,直接用Q查询或的关系来解决

        if user and user.check_password(password):
            # 使用了auth_user表后具有的方法check_password
            return user
        else:
            # 用户不存在或密码错误  这里的代码,还是在全局钩子中执行,全局钩子校验失败,要抛异常,所以在这抛异常
            raise APIException('用户不存在或密码错误')


    def _get_token(self, user):
        payload = jwt_payload_handler(user)
        token = jwt_encode_handler(payload)
        # 这两行代码可以到jwt的源码里面的序列化类的文件里面去复制
        return token

-----------------------------------------------------

.
.
.
.
.
.
.
.
.
.

6 腾讯云短信申请


# 发送短信接口,借助于第三方短信平台,收费的
	-腾讯云短信
	-阿里 大于短信
	-。。。。

---------------------------------------



# 使用腾讯短信
	https://cloud.tencent.com,微信扫码登录
	先点产品,再在搜索框里面搜索短信,回车调到短信的页面
	https://console.cloud.tencent.com/smsv2

	1 创建短信签名:公众号注册,提交等待审核通过
	2 需要先申请微信公众号,用网站或app认证比较烦

	3 创建短信正文模版
	-等待审核
	-发送短信
		python代码发送昂短信



------------------------------------------------

 # API SDK

-API: 腾讯自己的API接口,我们要带着数据向对应的地址发送post请求,
        然后腾讯会根据我们post携带的对应数据,发送对应的短信给对应的人
       写起来比较麻烦,要自己分析腾讯的接口
------------------------------------------------

-SDK:集成开发工具包,分语言,java,python,go
	-使用python 对api进行封装成包
	-以后我们只需要,安装包,导入包,包名.发送短信,传入参数,就可以发送了

------------------------------------------------

-只要官方提供sdk,优先用sdk
	先下载adk的模块
	pip install tencentcloud-sdk-python

创建签名与模板,用了标准模板后,发现模板里面只能发6位以下的数字,很垃圾!
image
.
image
.
点过去
image
.
python sdk
image
.
安装python项目里面安装sdk模块
image
.
把发送短信的代码整体复制到,python文件里面去,对应参数改好,右键运行,就行了
image
.
需要改这5个参数
image
image
.
还要改的参数
image
.
.
要创一个应用,用sdk发送短信需要用到应用的id号
image
.

.
.

补充

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

.
.
.

作业

# 练习使用pycharm操作git
# 手机号是否存在
# 多方式登录接口

# 注册公众号
# 注册云短信,申请

# 使用python 测试发送短信
posted @   tengyifan  阅读(38)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
点击右上角即可分享
微信分享提示