线下线上仓库初始化

流程:
cd luffy/luffyapi
git remote
git remote -v
git push online(自定义) master
然后去码云上随便新建一个xyz仓库,复制粘贴SSH公钥到git命令窗口中
git push xyz master
git remote remove xyz (删除线上的仓库)
git remote -v
桌面新建文件temp
cd  temp/
git clone 线上公钥SSH链接(可以克隆到temp文件夹中)
cd  xyz/
赋值代码文件到xyz中
git add .
git commit -m '初始化'
git push xyz master
git status
git remote -v
git push origin master

仓库间通信要分支同步

流程:
桌面新建proj文件夹
cd proj/
git clone 线上公钥SSH链接(可以克隆到temp文件夹中)
新建一个文件temp.txt
git status
cd luffyapi/
git status
git add .
git status
git push origin master
git commit -m '新增temp文件'
然后去线上刷新一下就能看到了
git add .
git commit -m '删除temp文件'
git push origin master
git branch dev
git checkout dev
新建dev文件
git add .
git commit -m '新增dev文件'
git push origin master
git log
git push origin master:master
git push origin dev:master
然后去线上刷新一下就能看到了
git checkout master
git pull origin master(拉)
git checkout dev
git pull origin dev

协同开发版本冲突问题(重点)

先拉项目(git pull origin master(拉)),然后新增文件,写代码,

让添加好的开发者,添加文件名相同的文件,代码行相同的位置写上相同或者不同的代码然后提交,

然后添加,切换分支,拉项目,然后打开编辑相同的文件夹,会提示:被修改

然后进去修改整合就能解决版本冲突了,然后在执行push提交

远程仓库回滚

git reflog
可以回滚到之前的版本,
git reset --hard 9d82 (后面 跟上面一条命令执行过后显示的版本号)
git push origin dev
git push origin dev -f
git reflog

远程仓库合并分支

可以设置master为:保护分支

其他的为:常规分支

编辑桌面proj文件中的manage.py文件:(#线下脚本文件 )
编辑桌面proj文件中的manage_prod.py文件:(#线上脚本文件 )
git checkout master
git checkout dev
git add .
git commit -m '修订脚本文件'
git checkout master
git checkout dev
git pull origin dev
git push origin dev
到码云仓库中dev分支点击,可以合并(dev——>py-trabe——>master)
下面可以写:修订脚本文件标题
说明:随便写一下,可以根据修订的脚本进行说明解释
还可以添加测试人员,自己为审核管理员,其他是测试人员,
可以选择标签,比如feature,bug
其他,可以选择1:必须审查代码、2:必须测试、4:合并后关闭提到的任务 不选择3:合并后删除提交分支(也可以删,一般不会操作)
创建
确认测试了(必须有一个测试确认),点击测试通过,审核通过了,可以发评论,最后合并分支。
git checkout master
git pull origin master
可以看到合并的分支
https://images.cnblogs.com/cnblogs_com/gfhh/1628579/o_200107170515QQ%E5%9B%BE%E7%89%8720200107204948.png

腾讯云短信服务

"""
1、注册微信公众号平台
2、注册开发者账号
3、创建短信应用
4、创建签名与模板
"""

短信功能不封装

导入腾讯云短信接口pip install qcloudsms_py

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

# 短信模板ID,需要在短信控制台中申请
template_id = 517040  # NOTE: 这里的模板 ID`7839`只是示例,真实的模板 ID 需要在短信控制台中申请
# 签名,参数使用的是`签名内容`
sms_sign = "小阿峰啊公众号"  # NOTE: 签名参数使用的是`签名内容`,而不是`签名ID`。这里的签名"腾讯云"只是示例,真实的签名需要在短信控制台中申请

from qcloudsms_py import SmsSingleSender
sender = SmsSingleSender(appid, appkey)
import random
def get_code():
    code=''
    for i in range(6):
        code+=str(random.randint(0,9))
    return code

code=get_code()
print(code)
# params = ["5678", 5]  # 当模板没有参数时,`params = []`
# 需要发送短信的手机号码
mobile = "17356530633"
try:
    response = sender.send_with_param(86, mobile,template_id,(code,5) , sign=sms_sign, extend="", ext="")
    if response and response.get('result')==0:
        print('ok')
    print(response)
except Exception as e:
    print(e)

短信功能的二次封装

libs/tx_sms/settings.py
# 短信应用 SDK AppID
APP_ID = 1400303014  # SDK AppID 以1400开头

# 短信应用 SDK AppKey
APP_KEY = "fe256e50a2d3e8d3cd07f21c42802ad3"

# 短信模板ID,需要在短信控制台中申请
TEMPLATE_ID = 517040  # NOTE: 这里的模板 ID`7839`只是示例,真实的模板 ID 需要在短信控制台中申请

# 签名,参数使用的是`签名内容`
SMS_SIGN = "小阿峰啊公众号"  # NOTE: 签名参数使用的是`签名内容`,而不是`签名ID`。这里的签名"腾讯云"只是示例,真实的签名需要在短信控制台中申请
libs/tx_sms/sms.py
import random


# 获取六位数字验证码
def get_sms_code():
    code = ''
    for i in range(6):
        code += str(random.randint(0, 9))
    return code


from qcloudsms_py import SmsSingleSender
from .sesttings import APP_ID, APP_KEY, TEMPLATE_ID, SMS_SIGN

sender = SmsSingleSender(APP_ID, APP_KEY)
from utils.logging import logger


def send_sms(mobile, code, exp):
    try:
        response = sender.send_with_param(86, mobile, TEMPLATE_ID, (code, exp), sign=SMS_SIGN, extend="", ext="")
        if response and response.get('result') == 0:
            return True
        logger.error('短信发送失败,状态码:%s,错误信息:%s' % (response.get('result'), response.get('errmsg')))
    except Exception as e:
        logger.error('短信发送异常,异常信息:%s' % e)
    return False
libs/tx_sms/__init__.py
from .sms import get_sms_code,send_sms

调用

from libs import tx_sms
code=tx_sms.get_sms_code()
print(code)
result=tx_sms.send_sms('17356530633',code,5)
if result:
    print('发送成功') 

多方式登录

https://images.cnblogs.com/cnblogs_com/gfhh/1628579/o_200107170609注册业务图.png
https://images.cnblogs.com/cnblogs_com/gfhh/1628579/o_200107170605登录业务图.png

视图层

import re
from rest_framework.views import APIView
from . import serializers
from utils.response import APIResponse

# Create your views here.

# 多方式登录
class LoginAPIView(APIView):
    #认证权限一定要局部禁用
    authentication_classes = ()
    permission_classes = ()

    def post(self,request,*args,**kwargs):
        serializer=serializers.LoginModelSerializer(data=request.data)
        serializer.is_valid(raise_exception=True)# 内部在全局钩子中完成token的签发
        return APIResponse(results={
            'username':serializer.content.get('user').username,
            'token':serializer.content.get('token')
        })

序列化

import re
from rest_framework import serializers
from rest_framework_jwt.serializers import jwt_payload_handler,jwt_encode_handler
from . import models
class LoginModelSerializer(serializers.ModelSerializer):
    #post请求,序列化默认当做create动作进行校验,需要校验数据库,create动作username会抛用户已存在异常
    #抛用户已存在异常是多余的,所有自定义系统校验规则即可

    username=serializers.CharField(min_length=3,max_length=16)
    password=serializers.CharField(min_length=3,max_length=16)

    class Meta:
        model=models.User
        fields=('username','password')

    #用全局钩子,完成token的签发
    def validate(self, attrs):
        #通过username和password完成多方式登录校验,得到user对象
        user=self._validata_user(attrs)
        #user对象包装payload载荷
        payload=jwt_payload_handler(user)
        #payload载荷签发token
        token=jwt_encode_handler(payload)
        #将user与token存储到serilizer对象中,方便在视图类中使用
        self.content={
            'user':user,
            'token':token
        }
        return attrs

    def _validata_user(self,attr):
        username=attr.get('username')
        password=attr.get('password')

        if re.match(r'.*@.*',username):#邮箱
            user=models.User.objects.filter(email=username).first()
        elif re.match(r'^1[3-9][0-9]{9}$',username):#电话
            user=models.User.objects.filter(mobile=username).first()
        else:#用户名
            user=models.User.objects.filter(username=username).first()

        if not user or not user.check_password(password):
            raise serializers.ValidationError({'message':'用户信息异常'})
        return user

验证码发送

视图层

#发送验证码
from libs import tx_sms
from django.core.cache import cache
from django.conf import settings

class SMSAPIView(APIView):
    authentication_classes = ()
    permission_classes = ()

    def post(self, request, *args, **kwargs):
        #处理手机号
        mobile=request.data.get('mobile',None)
        if not mobile:
            return APIResponse(1, msg='mobile字段必须', http_status=400)

        if not re.match(r'^1[3-9][0-9]{9}$',mobile):
            return APIResponse(1, msg='mobile格式有误', http_status=400)

        #生成验证码
        code=tx_sms.get_sms_code()

        #发送验证码
        result=tx_sms.send_sms(mobile,code,settings.SMS_EXP//60)

        if not result:
            return APIResponse(1, msg='验证码发送失败')

        #缓存验证码
        print(settings.SMS_EXP)
        cache.set(settings.SMS_CACHE_FORMAT % mobile,code,settings.SMS_EXP)

        #成功响应
        return APIResponse(0,msg='验证码发送成功')

const.py

# 短信验证码缓存key
SMS_CACHE_FORMAT = 'sms_cache_%s'

# 短信过期时间s
SMS_EXP = 3000000

手机登录

视图层

# 手机验证码登录
class LoginMobileAPIView(APIView):
    # 认证权限一定要局部禁用
    authentication_classes = ()
    permission_classes = ()

    def post(self, request, *args, **kwargs):
        serializer = serializers.LoginMobileModelSerializer(data=request.data)
        serializer.is_valid(raise_exception=True)  # 内部在全局钩子中完成token的签发
        return APIResponse(results={
            'username': serializer.content.get('user').username,
            'token': serializer.content.get('token')
        })

序列化

from django.core.cache import cache
from django.conf import settings
class LoginMobileModelSerializer(serializers.ModelSerializer):
    mobile=serializers.CharField(min_length=11,max_length=11)
    code=serializers.CharField(min_length=6,max_length=6)

    class Meta:
        model=models.User
        fields=('mobile','code')

    #验证码格式内容有误就不需要进行 取服务器存储的验证码(IO操作)进行校验
    def validate_code(self,value):
        try:
            int(value)
            return value
        except:
            raise serializers.ValidationError('验证码有误')

    def validate(self, attrs):
        mobile=attrs.get('mobile')
        code=attrs.pop('code')
        #那服务器缓存的验证码
        old_code=cache.get(settings.SMS_CACHE_FORMAT % mobile)

        if code!=old_code:
            raise serializers.ValidationError({'code': '验证码有误'})

        try:
            user = models.User.objects.get(mobile=mobile, is_active=True)
        except:
            raise serializers.ValidationError({'mobile': '该用户不存在'})

        payload=jwt_payload_handler(user)
        token=jwt_encode_handler(payload)
        self.content = {
            'user': user,
            'token': token
        }
        return attrs

复习

"""
1、轮播图接口
	BaseModel:is_delete、is_show、orders、update_time、created_time
	Banner:title、image、link
	
2、git:版本控制器
	客户端与服务器整合安装,任何一个客户端都可以作为服务器使用,所以可以做集群部署
	可以采用多分支进行开发,各分支之间相互独立,可以通过合并分支将分支间的信息同步
	
3、git命令
	git init [仓库名]
	git status
	git checkout .
	git add .
	git reset HEAD .
	git commit -m '信息'
	git reset --hard 版本号
	git branch [新分支]
	git checkout 分支名
	git merge 分支
	git remote [-v]
	git remote add 源码 地址
	git remote remove 源码
	git log | reflog

4、过滤文件
# .gitignore 文件
# 1)在仓库根目录下创建该文件
# 2)文件与文件夹均可以被过滤
# 3)文件过滤语法

过滤文件内容
文件或文件夹名:代表所有目录下的同名文件或文件夹都被过滤
/文件或文件夹名:代表仓库根目录下的文件或文件夹被过滤

eg:
a.txt:项目中所有a.txt文件和文件夹都会被过滤
/a.txt:项目中只有根目录下a.txt文件和文件夹会被过滤
/b/a.txt:项目中只有根目录下的b文件夹下的a.txt文件和文件夹会被过滤
*x*:名字中有一个x的都会被过滤(*代表0~n个任意字符)
空文件夹不会被提交,空包会被提交


5、线上线下操作
	1)线下仓库准备就绪
		将项目根文件夹初始化为仓库
		在仓库中建立过滤文件设置过滤规则
		将项目代码提交到本地版本库
	2)线上仓库
		建立一个公开的空白仓库,不能新建任何文件(空仓库不会初始化,没有.git文件夹)
"""