六、注册功能的实现
六、1将用户提交的注册数据保存在数据库
1.创建一个ORM模型,并且在数据库创建该表
models.py
from exts import db
from datetime import datetime
class EmailCaptchaModel(db.Model):
__tablename__ = "email_captcha"
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
email = db.Column(db.String(100), nullable=False, unique=True)
captcha = db.Column(db.String(10), nullable=False)
create_time = db.Column(db.DateTime, default=datetime.now)
class UserModel(db.Model):
__tablename__ = "user"
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
username = db.Column(db.String(200), nullable=False, unique=True)
email = db.Column(db.String(100), nullable=False, unique=True)
password = db.Column(db.String(200), nullable=False)
join_time = db.Column(db.DateTime, default=datetime.now)
2.完善前端代码,比如各个输入框的完善,加入name可以进行定位。加入用户名
register.html
{% extends "base.html" %}
{% block title %}注册{% endblock %}
{% block head %}
{% endblock %}
{% block body %}
<div class="row mt-4">
<div class="col"></div>
<div class="col">
<form method="POST" action="{{ url_for('user.register') }}">
<div class="form-group">
<label for="exampleInputEmail1">邮箱</label>
<input type="email" class="form-control" id="exampleInputEmail1" aria-describedby="emailHelp" name="email">
<small id="emailHelp" class="form-text text-muted">We'll never share your email with anyone else</small>
</div>
<div class="form-group">
<label for="exampleInputEmail1">验证码</label>
<div class="input-group">
<input type="text" class="form-control" name="captcha">
<div class="input-group-append">
<button class="btn btn-outline-secondary" type="button" id="captcha-btn">获取验证码</button>
</div>
</div>
</div>
<div class="form-group">
<label for="exampleInputEmail1">用户名</label>
<input type="text" class="form-control" name="username">
</div>
<div class="form-group">
<label for="exampleInputPassword1">密码</label>
<input type="password" class="form-control" id="exampleInputPassword1" name="password">
</div>
<div class="form-group">
<label for="exampleInputPassword1">确认密码</label>
<input type="password" class="form-control" name="password_confirm">
</div>
<button type="submit" class="btn btn-primary btn-block">立即注册</button>
</form>
</div>
<div class="col"></div>
</div>
{% endblock %}
3.新建forms.py表单,用于验证验证码和邮箱,需要在user.py导入
import wtforms
from wtforms.validators import length,email,EqualTo,InputRequired
from models import EmailCaptchaModel,UserModel
class LoginForm(wtforms.Form):
email = wtforms.StringField(validators=[email()])
password = wtforms.StringField(validators=[length(min=6,max=20)])
class RegisterForm(wtforms.Form):
username = wtforms.StringField(validators=[length(min=3,max=20)])
email = wtforms.StringField(validators=[email()])
captcha = wtforms.StringField(validators=[length(min=4, max=4)])
password = wtforms.StringField(validators=[length(min=6,max=20)])
password_confirm = wtforms.StringField(validators=[EqualTo("password")])
def validate_captcha(self,field):
captcha = field.data
email = self.email.data
captcha_model = EmailCaptchaModel.query.filter_by(email=email).first()
if not captcha_model or captcha_model.captcha.lower() != captcha.lower():
raise wtforms.ValidationError("邮箱验证码错误!")
def validate_email(self,field):
email = field.data
user_model = UserModel.query.filter_by(email=email).first()
if user_model:
raise wtforms.ValidationError("邮箱已经存在!")
models.py
from exts import db
from datetime import datetime
class EmailCaptchaModel(db.Model):
__tablename__ = "email_captcha"
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
email = db.Column(db.String(100), nullable=False, unique=True)
captcha = db.Column(db.String(10), nullable=False)
create_time = db.Column(db.DateTime, default=datetime.now)
class UserModel(db.Model):
__tablename__ = "user"
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
username = db.Column(db.String(200), nullable=False, unique=True)
email = db.Column(db.String(100), nullable=False, unique=True)
password = db.Column(db.String(200), nullable=False)
join_time = db.Column(db.DateTime, default=datetime.now)
user.py
import random
import string
from flask import Blueprint, render_template, request, redirect, url_for
from blueprints.forms import RegisterForm
from exts import mail, db
from flask_mail import Message
from models import EmailCaptchaModel, UserModel
from datetime import datetime
from werkzeug.security import generate_password_hash,check_password_hash #加密解密
bp = Blueprint("user", __name__, url_prefix="/user")
@bp.route("/login")
def login():
return render_template("login.html")
@bp.route("/register",methods=['GET','POST'])
def register():
if request.method == 'GET':
return render_template("register.html")
else:
form = RegisterForm(request.form)
if form.validate():
email = form.email.data
username = form.username.data
password = form.password.data
#md5利用hash加密
hash_password=generate_password_hash(password)
user = UserModel(email=email, username=username, password=hash_password)
db.session.add(user)
db.session.commit()
return redirect(url_for("user.login"))
else:
return redirect(url_for("user.register"))
@bp.route("/captcha",methods=['POST'])
def get_captcha():
email = request.args.get("email")
letter = string.ascii_letters + string.digits
captcha = "".join(random.sample(letter, 4))
if email:
message = Message(
subject='邮箱测试',
recipients=['需要注册的邮箱'],
body=f"您的注册验证码是:{captcha},请不要告诉任何人哦!"
)
mail.send(message)
#判断邮箱是否存在,诺存在,更新数据库中得验证码
captcha_model = EmailCaptchaModel.query.filter_by(email=email).first()
if captcha_model:
captcha_model.captcha = captcha
captcha_model.create_time = datetime.now()
db.session.commit()
else:
captcha_model = EmailCaptchaModel(email=email, captcha=captcha)
db.session.add(captcha_model)
db.session.commit()
return "success"
else:
return "没有传递邮箱"
六、2 发送AJAX请求
实现功能:给服务器发送获取验证码的请求,前端提示验证码发送成功,添加验证码倒计时
需要用到js,整个网页全部加载完成再绑定点击事件
获取验证码
用到的所有文件:
其中jquery.3.6.min.js可以在jquery.3.6.min.js下载
通过js绑定点击事件
register.js
function bindCaptchaBtnClick() {
$("#captcha-btn").on("click", function (event) {
var $this = $(this);
var email = $("input[name='email']").val();
if (!email) {
alert("请先输入邮箱!");
return;
}
// 通过js发送网络请求:ajax。Async JavaScript And XML(JSON)
// Jinja2
$.ajax({
url: "/user/captcha",
method: "POST",
data: {
"email": email
},
success: function (res) {
var code = res['code'];
if (code == 200) {
// 取消点击事件
$this.off("click");
// 开始倒计时
var countDown = 60;
var timer = setInterval(function () {
countDown -= 1;
if (countDown > 0) {
$this.text(countDown + "秒后重新发送");
} else {
$this.text("获取验证码");
// 重新执行下这个函数,重新绑定点击事件
bindCaptchaBtnClick();
// 如果不需要倒计时了,那么就要记得清除倒计时,否则会一直执行下去
clearInterval(timer);
}
}, 1000);
alert("验证码发送成功!");
} else {
alert(res['message']);
}
}
})
});
}
// 等网页文档所有元素都加载完成后再执行
$(function () {
bindCaptchaBtnClick();
});
user.py
import random
import string
from flask import Blueprint, render_template, request, redirect, url_for, jsonify
from blueprints.forms import RegisterForm
from exts import mail, db
from flask_mail import Message
from models import EmailCaptchaModel, UserModel
from datetime import datetime
from werkzeug.security import generate_password_hash, check_password_hash # 加密解密
bp = Blueprint("user", __name__, url_prefix="/user")
@bp.route("/login")
def login():
return render_template("login.html")
@bp.route("/register", methods=['GET', 'POST'])
def register():
if request.method == 'GET':
return render_template("register.html")
else:
form = RegisterForm(request.form)
if form.validate():
email = form.email.data
username = form.username.data
password = form.password.data
# md5利用hash加密
hash_password = generate_password_hash(password)
user = UserModel(email=email, username=username, password=hash_password)
db.session.add(user)
db.session.commit()
return redirect(url_for("user.login"))
else:
return redirect(url_for("user.register"))
@bp.route("/captcha", methods=['POST'])
def get_captcha():
# GET,POST
email = request.form.get("email")
letters = string.ascii_letters + string.digits
captcha = "".join(random.sample(letters, 4))
if email:
message = Message(
subject="邮箱测试",
recipients=[email],
body=f"【知了问答】您的注册验证码是:{captcha},请不要告诉任何人哦!"
)
mail.send(message)
captcha_model = EmailCaptchaModel.query.filter_by(email=email).first()
if captcha_model:
captcha_model.captcha = captcha
captcha_model.create_time = datetime.now()
db.session.commit()
else:
captcha_model = EmailCaptchaModel(email=email, captcha=captcha)
db.session.add(captcha_model)
db.session.commit()
print("captcha:", captcha)
# code: 200,成功的、正常的请求
return jsonify({"code": 200})
else:
# code:400,客户端错误
return jsonify({"code": 400, "message": "请先传递邮箱!"})
点击确定之后开始倒计时。
在网站中输入注册之后,数据库收到用户名,密码,注册时间,至此注册功能完成。