DAY 80 git02

1 git的操作基本操作
-三个区:工作区,暂存区,版本库
   -git add .
   -git commit -m ‘注释’
   -工作区改了内容(改的是被版本管理的内容)git checkout .
   -工作区回复到某个版本: git reset --hard 版本号
   -从暂存区拉回工作区:git reset .
   -git status
   -git log
   -git reflog
 
2 忽略文件
-在项目根路径下建立.gitignore
   -在文件中写内容
  log    忽略所有log文件夹
       /log   忽略根路径下的log
       *      任意长度的字符
       *.log  忽略以.log结尾的文件
       /luffyapi/apps
  -咱们写的
      .idea
       *.log
       scripts
       __pycache__
       #luffyapi/apps/*/migrations
       */*/*/migrations/*.py
       !*/*/*/migrations/__init__.py
       
3 分支
-查:git branch   #*和绿色在哪,表示在当前分支
-增:git branch dev
   -删:git branch -D dev # 不在该分支才能删除
   -切换:git checkout dev
   -合并:git merge dev   # 往我身上合并,不要在dev分支执行
4 pycharm操作git
-使用pycharm新建,删除,切换分支
   -初始化仓库
   -提交到暂存区
   -提交到版本库
   -建立远程仓库
   
5 远程仓库
-查看远程仓库 git remote
   -新增远程仓库 git remote add 远程仓库名字 远程地址
   -把代码提交到远程仓库 git push 远程仓库名字 分支名
   -从远程仓库拉取代码  git pull origin master
   
6 ssh连接远程仓库
-非对称加密(对称加密)
-本地生成公钥私钥(用户家路径生成.ssh文件夹,公钥和私钥)
   -拿着公钥配置在gitee的ssh里面
   -以后再提交使用ssh方式提交(remote地址得改)

 

1 协同开发

1 多人开发同一个项目
2 现在你们git clone 项目,在你本地了
3 可以改代码了,当你git  push 的时候,提交不了
4 项目管理员分配给你权限(gitee中管理--》仓库成员--》邀请成员)
5 这一个项目有一个管理员,若干开发者
6 重点:不能夸版本提交,只能先拉到最新,再提交
7 如果某个开发者再s1.py 的第14行加入了东西,我也加入了,他先提交(它没问题)
8 当我再拉取,出冲突了
   <<<<<<< HEAD
   你的代码
  =======
   同事的代码
   >>>>>>> d78b8fb39f6469e810868218a052bc3174b3e1fc

9 解决冲突
-留你的代码:你写的好
   -留他的代码:你觉得他写的好
   -你们的都留着:你俩虽然改了一行,但是功能不一样

 

2 分支合并

1 版本库又两套
-本地一套
  -本地有master,dev分支
   -远程一套
  -远程现在只有master分支
2 把本地dve提交到远端
git push origin dev
   现在远端有两个分支 master和dev
3 删除本地分支,删除远程分支(点点点)

4 直接在远程创建分支(点点点)
5 把远端的dev拉到本地

 

2.1 线上分支合并

1 在线上新建一个dev1分支
2 拉去到本地
3 在本地dev1分支增加一行代码,提交到版本库
4 在本地dev1分支又增加一行代码,提交到版本库
5 远程分支合并
-pull request,指定从哪个分支合并到哪个分支
   -绿色表示没有冲突,可以正常合并
   -普通和扁平化(变基)
6 本地、远程的dev1和master就完全一样了

 

 

2.2 线下分支合并提交

1 本地dev1分支新增代码,提交到版本库
2 本地dev1分支合并到master
-切到master
   -git merge dev1 (没有冲突直接合并)
   -git push origin master (本地master提交到远端master)
3 切到dev1分支,再提交到远端
4 到此,本地分支合并完成,远端的dev1跟master完全一样,本地的dev1跟master也完全一样

 

2.3 合并分支冲突解决

1 再master加一行,提交到版本库
2 再dev1同样尾增增加一行,提交到版本库
3 把dev1合并到master,就会出冲突
-切到master分支
   -git merge dev1  有冲突
   -解决冲突(到底留什么,你觉得)
   -提交到远端

 

 

3 远程仓库回滚

1 远程仓库,回到最初路飞第一次提交的地方
2 再本地回复到第一次提交
git reste --hard 59dbf80c
   git push origin master -f # 强制提交
   
3 切记 -f 清醒的时候使用

 

 

4 其他了解

git flow
-是一种建分支的方案
   -预览分支,开发分支,bug分支,主分支,测试分支...
pull和fetch区别
git pull:拉代码+合并
   git fetch:拉代码,需要手动合进去
变基rebase
-合并分支的时候,是否保留之前分支的日志
   
   
git客户端:
-官方下载的一个(命令行下)
   -pycharm编辑器
   -sourcetree:美观,分支通过不同颜色线上,看着好看

5 登陆页面分析

<template>
<div class="login">
<span @click="close_login">X</span>
</div>
</template>

<script>
export default {
name: "Login",
methods:{
close_login(){
//子传父组件 this.$emit,给父组件传递一个事件
this.$emit("close")
},

},

}
</script>

<style scoped>
.login{
100vw;
height: 100vw;
position: fixed;
left: 0;
top: 0;
z-index: 666;

}
span{
font-size: 30px;
cursor: pointer;
}
</style>

 

6 前端登陆注册编写

Login.vue

<template>
<div class="login">
<div class="box">
<i class="el-icon-close" @click="close_login"></i>
<div class="content">
<div class="nav">
<span :class="{active: login_method === 'is_pwd'}"
@click="change_login_method('is_pwd')">密码登录</span>
<span :class="{active: login_method === 'is_sms'}"
@click="change_login_method('is_sms')">短信登录</span>
</div>
<el-form v-if="login_method === 'is_pwd'">
<el-input
placeholder="用户名/手机号/邮箱"
prefix-icon="el-icon-user"
v-model="username"
clearable>
</el-input>
<el-input
placeholder="密码"
prefix-icon="el-icon-key"
v-model="password"
clearable
show-password>
</el-input>
<el-button type="primary">登录</el-button>
</el-form>
<el-form v-if="login_method === 'is_sms'">
<el-input
placeholder="手机号"
prefix-icon="el-icon-phone-outline"
v-model="mobile"
clearable
@blur="check_mobile">
</el-input>
<el-input
placeholder="验证码"
prefix-icon="el-icon-chat-line-round"
v-model="sms"
clearable>
<template slot="append">
<span class="sms" @click="send_sms">{{ sms_interval }}</span>
</template>
</el-input>
<el-button type="primary">登录</el-button>
</el-form>
<div class="foot">
<span @click="go_register">立即注册</span>
</div>
</div>
</div>
</div>
</template>

<script>
export default {
name: "Login",
data() {
return {
username: '',
password: '',
mobile: '',
sms: '',
login_method: 'is_pwd',
sms_interval: '获取验证码',
is_send: false,
}
},
methods: {
close_login() {
this.$emit('close')
},
go_register() {
this.$emit('go')
},



change_login_method(method) {
this.login_method = method;
},
check_mobile() {
if (!this.mobile) return;
if (!this.mobile.match(/^1[3-9][0-9]{9}$/)) {
this.$message({
message: '手机号有误',
type: 'warning',
duration: 1000,
onClose: () => {
this.mobile = '';
}
});
return false;
}
this.is_send = true;
},
send_sms() {

if (!this.is_send) return;
this.is_send = false;
let sms_interval_time = 60;
this.sms_interval = "发送中...";
let timer = setInterval(() => {
if (sms_interval_time <= 1) {
clearInterval(timer);
this.sms_interval = "获取验证码";
this.is_send = true; // 重新回复点击发送功能的条件
} else {
sms_interval_time -= 1;
this.sms_interval = `${sms_interval_time}秒后再发`;
}
}, 1000);
}
}
}
</script>

<style scoped>
.login {
100vw;
height: 100vh;
position: fixed;
top: 0;
left: 0;
z-index: 10;

}

.box {
400px;
height: 420px;

border-radius: 10px;
position: relative;
top: calc(50vh - 210px);
left: calc(50vw - 200px);
}

.el-icon-close {
position: absolute;
font-weight: bold;
font-size: 20px;
top: 10px;
right: 10px;
cursor: pointer;
}

.el-icon-close:hover {
color: darkred;
}

.content {
position: absolute;
top: 40px;
280px;
left: 60px;
}

.nav {
font-size: 20px;
height: 38px;
border-bottom: 2px solid darkgrey;
}

.nav > span {
margin: 0 20px 0 35px;
color: darkgrey;
user-select: none;
cursor: pointer;
padding-bottom: 10px;
border-bottom: 2px solid darkgrey;
}

.nav > span.active {
color: black;
border-bottom: 3px solid black;
padding-bottom: 9px;
}

.el-input, .el-button {
margin-top: 40px;
}

.el-button {
100%;
font-size: 18px;
}

.foot > span {
float: right;
margin-top: 20px;
color: orange;
cursor: pointer;
}

.sms {
color: orange;
cursor: pointer;
display: inline-block;
70px;
text-align: center;
user-select: none;
}
</style>

 

Register.vue

<template>
<div class="register">
<div class="box">
<i class="el-icon-close" @click="close_register"></i>
<div class="content">
<div class="nav">
<span class="active">新用户注册</span>
</div>
<el-form>
<el-input
placeholder="手机号"
prefix-icon="el-icon-phone-outline"
v-model="mobile"
clearable
@blur="check_mobile">
</el-input>
<el-input
placeholder="密码"
prefix-icon="el-icon-key"
v-model="password"
clearable
show-password>
</el-input>
<el-input
placeholder="验证码"
prefix-icon="el-icon-chat-line-round"
v-model="sms"
clearable>
<template slot="append">
<span class="sms" @click="send_sms">{{ sms_interval }}</span>
</template>
</el-input>
<el-button type="primary">注册</el-button>
</el-form>
<div class="foot">
<span @click="go_login">立即登录</span>
</div>
</div>
</div>
</div>
</template>

<script>
export default {
name: "Register",
data() {
return {
mobile: '',
password: '',
sms: '',
sms_interval: '获取验证码',
is_send: false,
}
},
methods: {
close_register() {
this.$emit('close', false)
},
go_login() {
this.$emit('go')
},
check_mobile() {
if (!this.mobile) return;
if (!this.mobile.match(/^1[3-9][0-9]{9}$/)) {
this.$message({
message: '手机号有误',
type: 'warning',
duration: 1000,
onClose: () => {
this.mobile = '';
}
});
return false;
}
this.is_send = true;
},
send_sms() {
if (!this.is_send) return;
this.is_send = false;
let sms_interval_time = 60;
this.sms_interval = "发送中...";
let timer = setInterval(() => {
if (sms_interval_time <= 1) {
clearInterval(timer);
this.sms_interval = "获取验证码";
this.is_send = true; // 重新回复点击发送功能的条件
} else {
sms_interval_time -= 1;
this.sms_interval = `${sms_interval_time}秒后再发`;
}
}, 1000);
}
}
}
</script>

<style scoped>
.register {
100vw;
height: 100vh;
position: fixed;
top: 0;
left: 0;
z-index: 10;

}

.box {
400px;
height: 480px;

border-radius: 10px;
position: relative;
top: calc(50vh - 240px);
left: calc(50vw - 200px);
}

.el-icon-close {
position: absolute;
font-weight: bold;
font-size: 20px;
top: 10px;
right: 10px;
cursor: pointer;
}

.el-icon-close:hover {
color: darkred;
}

.content {
position: absolute;
top: 40px;
280px;
left: 60px;
}

.nav {
font-size: 20px;
height: 38px;
border-bottom: 2px solid darkgrey;
}

.nav > span {
margin-left: 90px;
color: darkgrey;
user-select: none;
cursor: pointer;
padding-bottom: 10px;
border-bottom: 2px solid darkgrey;
}

.nav > span.active {
color: black;
border-bottom: 3px solid black;
padding-bottom: 9px;
}

.el-input, .el-button {
margin-top: 40px;
}

.el-button {
100%;
font-size: 18px;
}

.foot > span {
float: right;
margin-top: 20px;
color: orange;
cursor: pointer;
}

.sms {
color: orange;
cursor: pointer;
display: inline-block;
70px;
text-align: center;
user-select: none;
}
</style>

Header.vue

<template>

<div>
<div class="slogan">
<p>老男孩IT教育 | 帮助有志向的年轻人通过努力学习获得体面的工作和生活</p>
</div>
<div class="nav">
<ul class="left-part">
<li class="logo">
<router-link to="/">
<img src="../assets/img/head-logo.svg" alt="">
</router-link>
</li>
<li class="ele">
<span @click="goPage('/free-course')" :class="{active: url_path === '/free-course'}">免费课</span>
</li>
<li class="ele">
<span @click="goPage('/actual-course')" :class="{active: url_path === '/actual-course'}">实战课</span>
</li>
<li class="ele">
<span @click="goPage('/light-course')" :class="{active: url_path === '/light-course'}">轻课</span>
</li>
</ul>

<div class="right-part">
<div>
<span @click="put_login">登录</span>
<span class="line">|</span>
<span @click="put_register">注册</span>


</div>
</div>


<Login v-if="is_login" @close="close_login" @go="put_register"/>
<Register v-if="is_register" @close="close_register" @go="put_login"/>
</div>

</div>
</template>

<script>
import Login from "../components/Login";
import Register from "../components/Register";

export default {
name: "Header",
data() {
return {
is_login: false,
is_register: false,
}
},
methods: {
put_login() {
this.is_login = true;
this.is_register = false;
},
put_register() {
this.is_login = false;
this.is_register = true;
},
close_login() {
this.is_login = false;
},
close_register() {
this.is_register = false;
}

},
components: {
Login, Register
}
}
</script>

<style scoped>
.header {

box-shadow: 0 0 5px 0 #aaa;
}

.header:after {
content: "";
display: block;
clear: both;
}

.slogan {

height: 40px;
}

.slogan p {
1200px;
margin: 0 auto;
color: #aaa;
font-size: 13px;
line-height: 40px;
}

.nav {

user-select: none;
1200px;
margin: 0 auto;

}

.nav ul {
padding: 15px 0;
float: left;
}

.nav ul:after {
clear: both;
content: '';
display: block;
}

.nav ul li {
float: left;
}

.logo {
margin-right: 20px;
}

.ele {
margin: 0 20px;
}

.ele span {
display: block;
font: 15px/36px '微软雅黑';
border-bottom: 2px solid transparent;
cursor: pointer;
}

.ele span:hover {
border-bottom-color: orange;
}

.ele span.active {
color: orange;
border-bottom-color: orange;
}

.right-part {
float: right;
}

.right-part .line {
margin: 0 10px;
}

.right-part span {
line-height: 68px;
cursor: pointer;
}
</style>

7 登录注册接口分析

1 多方式登录接口
2 校验手机号是否存在接口
3 手机号,密码,验证码注册接口
4 短信登录接口
5 发送短信接口(阿里大于短信,腾信的短信平台(刚注册免费100条))

8 多方式登录接口

路由

 


from django.urls import path,include
from . import views

from rest_framework.routers import SimpleRouter
router=SimpleRouter()
# /user/login 的post请求
router.register('',views.LoginView,'login')
urlpatterns = [

path('', include(router.urls)),

]

序列化类

from rest_framework import serializers
from rest_framework.exceptions import ValidationError
from . import models
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 UserModelSerializer(serializers.ModelSerializer):
# 必须重写一下username字段
username = serializers.CharField()

class Meta:
model = models.User
fields = ['username', 'password']
extra_kwargs = {
'username': {'write_only': True},
'password': {'write_only': True},

}

# 写全局钩子(校验用户名密码是否正确,登录成功,签发token)
def validate(self, attrs):
# 取出用户名密码
username = attrs.get('username')
password = attrs.get('password')
import re
if re.match('^1[3-9][0-9]{9}$', username):
user = models.User.objects.filter(mobile=username).first()
elif re.match('^.+@.+$', username):
user = models.User.objects.filter(email=username).first()
else:
user = models.User.objects.filter(username=username).first()
# 校验user,校验密码
if user and user.check_password(password):
# 签发token
payload = jwt_payload_handler(user)
token = jwt_encode_handler(payload)
self.context['token'] = token
self.context['user'] = user
return attrs

else:
raise ValidationError('用户名或密码错误')

视图类

from rest_framework.viewsets import ViewSetMixin,ViewSet
from rest_framework.views import APIView
from rest_framework.decorators import action
from .serializer import UserModelSerializer
# class LoginView(ViewSetMixin,APIView):
class LoginView(ViewSet):
@action(methods=['POST'],detail=False)
def login(self,request,*args,**kwargs):
# 序列化类
ser=UserModelSerializer(data=request.data)
if ser.is_valid():
# 登录成功
token=ser.context['token']
user=ser.context['user']
# ser2=UserModelSerializer(instance=user)
return APIResponse(token=token,username=user.username,id=user.id)
else:
# 登录失败
return APIResponse(code=101,msg=ser.errors)
原文地址:https://www.cnblogs.com/DEJAVU888/p/14893930.html