今天来具体实现注册功能。
01
—
注册页面
首先简单写一个注册页面。

<template>
<div class="bg">
<div id="register">
<h2>注册页面</h2>
<el-form ref="form" :model="form" label-width="20%">
<el-form-item label="用户名:">
<el-input v-model="form.username" placeholder="username" ></el-input>
</el-form-item>
<el-form-item label="密 码:">
<el-input v-model="form.password" type="password" placeholder="password" ></el-input>
</el-form-item>
<el-form-item label="邮 箱:">
<el-input v-model="form.email" placeholder="email"></el-input>
</el-form-item>
<el-form-item label="验证码:">
<el-input v-model="form.emailcode" style="width: 49%;margin-right: 2%;"></el-input>
<el-button type="primary" style="width: 49%;" @click="getcode">发送</el-button>
</el-form-item>
</el-form>
<el-button type="primary" round @click="register" class="btn">注册</el-button>
</div>
</div>
</template>
<script>
import { ElMessage } from 'element-plus' // eslint-disable-line no-unused-vars
import axios from 'axios'
export default {
data () {
return {
form: {
username: '用户名',
password: '密码',
email: 'xxxx@xx.com',
emailcode: ''
},
isnull: false
};
},
components: {
},
methods: {
register() {
if (this.form.username == '') {
this.$message.error('用户名不能为空');
} else if (this.form.password == '') {
this.$message.error('密码不能为空');
} else if (this.form.emailcode == '') {
this.$message.error('验证码不能为空');
} else {
axios.post('http://localhost:8000/api/register/', {
params: {
username: this.form.username,
password: this.form.password
}
}).then(res => {
if (res.data.status == 200) {
let self = this
self.$confirm("注册成功", "是否返回登录页", {
confirmButtonText: "确认",
cancelButtonText: "取消",
type:"success",
distinguishCancelAndClose: false, // 设置为true才会把右上角X和取消区分开来
closeOnClickModal: false
}).then(function () {
self.$router.push('/')
}).catch(function (e) {
if (e == 'cancel') {
console.log("取消");
}else if(e == 'close') {
console.log("取消");
}
})
} else if (res.data.status == 202) {
let self = this
self.$alert('用户名已存在', '注册失败', {
confirmButtonText: '确定',
callback: action => { // eslint-disable-line no-unused-vars
this.form.username = '',
this.form.password = ''
}
})
} else if (res.data.status == 203) {
let self = this
self.$alert('验证码错误', '注册失败', {
confirmButtonText: '确定',
callback: action => { // eslint-disable-line no-unused-vars
this.form.emailcode = ''
}
})
} else {
console.log(res.data.error);
}
}).catch(err => {
console.log('操作失败' + err);
})
}
}
}
}
</script>
<style scoped>
.bg {
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
background: url('../assets/login-bg3.jpg');
background-size: 100% 100%;
}
#register {
min-height: 40%;
width: 350px;
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.25);
background: #ffffff;
opacity: 0.85;
position: absolute;
top: 20%;
left: 40%;
text-align: center;
display: flex;
flex-direction: column;/*横向*/
padding: 30px;
}
#register h2 {
padding-bottom: 30px;
}
.btn {
width: 60%;
margin: auto;
}
</style>点击注册,控制台报错Access to XMLHttpRequest at 'http://localhost:8000/api/register/' from origin 'http://localhost:8081' has been blocked by CORS policy:

这个是跨域的问题。我们修改下请求地址:
从axios.post('http://localhost:8000/api/register/', {
改成axios.post('/api/register/', {
然后打包使用pycharm启动项目,嘿嘿不报错了,但是调试时候我们不能每次都打包吧,所以可以修改下设置。

修改setting文件:
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'corsheaders.middleware.CorsMiddleware',
'django.middleware.common.CommonMiddleware',
# 'django.middleware.csrf.CsrfViewMiddleware', #禁用csrf校验
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]修改回请求,再次开发运行,也不报错了,这样因为跨域校验去掉了。


02
—
调试接口连通性
页面有了我们看下注册接口。myapp下面的url文件添加路径:
re_path(r'^register/$', register.as_view(), name="api"新建视图类:这里只是先简单的获取下请求值以判断是否能获取到前端传值。
class register(APIView):
def post(self, request, *args, **kwargs):
# 如果headerkey为auth - token,即headers = {'auth-token': '1234'}
# 应该使用request.META.get("HTTP_AUTH_TOKEN")
# 获取 headerkey中的小写转为大写,横线“-”转为下划线“_”, 并且加上前缀HTTP
# 尤其注意headerkey中不应该包含HTTP前缀,以及符号"_", 否则会取不到对应的值
# params用于获取字符串,
# data:用于获取正文,
# post方法两个参数都可以使用,get方法只能使用params
print(request.META.get("HTTP_AUTH_TOKE",'321'))
print(request.data)
payload={'status': "200", 'message': "注册成功"}
return Response(payload)


前端到后端是通的。
03
—
邮箱验证码的实现
首先修改页面:

默认参数新增:
time: 0,
yzm_disabled: false,
yzm_txt: "获取验证码",调用sendcode函数:
<el-form-item label="验证码:">
<el-input v-model="form.emailcode" style="width: 49%;margin-right: 2%;"></el-input>
<el-button type="primary" :disabled=yzm_disabled style="width: 49%;" @click="sendcode">{{yzm_txt}}
</el-button>
</el-form-item>,
sendcode() {
var regEmail = /^[a-zA-Z0-9_-]+([-_.][a-zA-Z0-9_-]+)*@([a-zA-Z0-9_-]+[-.])+[a-zA-Z0-9_-]{2,5}$/;
if (this.form.email == '') {
alert("请输入邮箱");
} else if (!regEmail.test(this.form.email)) {
alert("邮箱格式不正确");
} else {
this.time = 60;
this.yzm_disabled = true;
this.timer();
axios.post('http://localhost:8000/api/sendcode/', {
email: this.form.email
}).then(res => {
console.log('发送成功'+res);
}).catch(err => {
console.log('操作失败' + err);
})
}
},
timer() {
if (this.time > 0) {
this.time--;
this.yzm_txt = this.time + "s后重新获取";
setTimeout(this.timer, 1000);
} else {
this.time = 0;
this.yzm_txt = "获取验证码";
this.yzm_disabled = false;
}
}
}编写邮箱工具类的方法:
#-*- codeing = utf-8 -*-
#@Time: 2022/5/29 20:54
#@Author: 怪盗LLYL
#@File: sendemail.py
#@Software: PyCharm
from email.header import Header
from email.mime.text import MIMEText
from email.utils import parseaddr, formataddr
from django_wx import settings
import smtplib
class MyEmail(object):
def sendemail(self,code,to_addr):
def _format_addr(s):
name, addr = parseaddr(s)
return formataddr((Header(name, 'utf-8').encode(), addr))
from_addr = settings.SEND_EMAIL# 发邮件的邮箱
password = settings.EMAIL_PASSWORD#授权码
to_addr = to_addr #目标
smtp_server ='smtp.163.com'# input('SMTP server: ')
msg = MIMEText('<html><body><p>验证码:' + code + '</p>' + '</body></html>', 'html', 'utf-8')
msg['From'] = _format_addr('测试开发真货 <%s>' % from_addr)
msg['To'] = _format_addr('登录用户 <%s>' % to_addr)
msg['Subject'] = Header('登录验证码', 'utf-8').encode() #邮件主题
server = smtplib.SMTP(smtp_server, 25)
server.set_debuglevel(1)
server.login(from_addr, password)
server.sendmail(from_addr, [to_addr], msg.as_string())
server.quit()
if __name__ == '__main__':
myemai = MyEmail()
myemai.sendemail('qwea','xxxxx@qq.com')
发送邮件需要打开服务,我用的是163的邮箱,需要打开SMTP服务,和获取授权码,其他邮箱同理。


增加路由和发验证码方法,修改注册方法
class sendcode(APIView):
def post(self, request, *args, **kwargs):
email = request.data['email']
code_list = []
for i in range(6): # 控制验证码的位数
state = random.randint(1, 3) # 生成状态码
if state == 1:
first_kind = random.randint(65, 90) # 大写字母
random_uppercase = chr(first_kind)
code_list.append(random_uppercase)
elif state == 2:
second_kinds = random.randint(97, 122) # 小写字母
random_lowercase = chr(second_kinds)
code_list.append(random_lowercase)
elif state == 3:
third_kinds = random.randint(0, 9)
code_list.append(str(third_kinds))
emailcode = "".join(code_list)
myemail = MyEmail()
myemail.sendemail(emailcode,email)
request.session['emailcode'] = emailcode
payload={'status': "200", 'message': "发送成功"}
return Response(payload)class register(APIView):
def post(self, request, *args, **kwargs):
# 如果headerkey为auth - token,即headers = {'auth-token': '1234'}
# 应该使用request.META.get("HTTP_AUTH_TOKEN")
# 获取 headerkey中的小写转为大写,横线“-”转为下划线“_”, 并且加上前缀HTTP
# 尤其注意headerkey中不应该包含HTTP前缀,以及符号"_", 否则会取不到对应的值
# params用于获取字符串,
# data:用于获取正文,
# post方法两个参数都可以使用,get方法只能使用params
# print(request.META.get("HTTP_AUTH_TOKE",'321'))
emailcode = request.data["emailcode"]
print(emailcode)
print(request.session.get('emailcode', None))
if emailcode == request.session.get('emailcode', None):
payload={'status': "200", 'message': "注册成功"}
else:
payload = {'status': "203", 'error': "验证码不正确"}
return Response(payload)注意:这里用到了session储存验证码,需要在前端启用。

输入错误验证码:

输入正确验证码:


04
—
预告
今天先到这吧,下一节我们将创建一个用户视图模型,并再注册时候新建用户记录,工作日更新会慢。