1 网站使用流程
所设计的网站页面跳转关系如下图所示:
2 登陆校验
2.1 前端JS输入有效性校验
HTML代码:
{% extends "base.html" %} <!--模板继承,父模板内容为顶栏与背景等网页统一布局-->
{% block title %}Login{% endblock %} <!--子模版网页标题-->
{% block head %}
<link rel="stylesheet" href="{{ url_for('static', filename='css/login.css') }}">
<script src="{{ url_for('static', filename='jquery/jquery.3.6.min.js') }}"></script>
<script src="{{ url_for('static', filename='js/login.js') }}"></script>
{% endblock %}
{% block content %}
<form method="POST" name="loginform"> <!--登陆表单-->
<div class="form-group">
<div class="loginformlabel"><label>用户名</label></div>
<input type="text" class="logininput" aria-describedby="emailHelp"
name="username" id="un1" onblur="logincheck1('#un1','#am1')" >
<!--用户名输入,失去焦点时触发JS校验事件“logincheck1”-->
<div class="alarmmessage1" id="am1"></div>
<!--放置错误信息的提示的盒子,内容待JS校验后写入-->
</div>
<div class="form-group">
<div class="loginformlabel"><label for="exampleInputPassword1">密码</label></div>
<input type="password" name="password" class="logininput" id="exampleInputPassword1" onblur="logincheck2('#exampleInputPassword1','#am2')" >
<!--密码输入,失去焦点时触发JS校验事件“logincheck2”-->
<div class="alarmmessage2" id="am2"></div>
<!--放置错误信息的提示的盒子,内容待JS校验后写入-->
</div>
<div class="form-group">
<button type="submit" class="loginbutton">立即登录</button> <!--登录(提交表单)按钮-->
</div>
</form>
{% if lof_errors == '用户名或密码错误!' %} <!--后端校验内容-->
<script type="text/javascript">alert("用户名或密码错误!")</script>
{% endif %}
{% endblock %}
JS代码:
//errSelector为对应的放置错误信息提示盒子
function switchValid(onOff,errSelector,message){ //控制错误信息内容的函数
if(onOff == false){
$(errSelector).text(message); //若校验失败,将错误提示信息写入errSelector
}
else
{
$(errSelector).text(""); //若校验成功,错误信息内容为空
}
}
//用户名输入有效性校验
function logincheck1(input,errSelector){
var a = $(input).val(); //获取用户输入的用户名
var str1 = a.toString(); //将其转换为字符串类型,以便检查长度
if (str1.length<3 || str1.length>20){
switchValid(false,errSelector,"用户名格式错误,长度应为3-20"); //校验失败,调用switchValid,传入校验结果与错误提示信息,将错误提示信息写入对应的提示盒子
return false;
} else{
switchValid(true,errSelector); //校验成功,调用函数但不传入message
return true;
}
}
//密码输入有效性校验,与用户名的校验同理
function logincheck2(input,errSelector){
var b = $(input).val();
var str2 = b.toString();
if (str2.length<6 || str2.length>20){
switchValid(false,errSelector,"密码格式错误,长度应为6-20");
return false;
} else {
switchValid(true, errSelector);
return true;
}
}
效果如图:
登录页:
正确输入用户名与密码:
用户名有效性校验失败:
用户名与密码有效性校验均失败:
2.2 后端用户信息校验
登陆页面视图函数:
@bp.route('/', methods=['GET', 'POST'])
def login():
if request.method == 'GET':
return render_template("login.html")
else: # 前端提交表单数据后进行验证
form = LoginForm(request.form) # 后端输入有效性验证
if form.validate(): # 后端有效性校验成功
username = form.username.data # 获取输入的用户名和密码
password = form.password.data
user = UserModel.query.filter_by(username=username).first() # 首先在数据库中查找用户是否存在(已注册)
if not user: # 查找不到用户,即用户不存在
return redirect(url_for('auth.register')) #重定向到注册页面
if check_password_hash(user.password, password): # 查找到了用户,检查密码是否正确
session['user_id'] = user.id # 若密码正确,则获取用户相关信息
return redirect("/index") #并重定向到个人主页
else: # 密码不正确
print("用户名或密码错误!")
var1 = '用户名或密码错误!'
return render_template("login.html", lof_errors=var1) # 返回错误信息到前端页面
else: #后端有效性校验失败
print(form.errors)
return redirect(url_for("auth.login")) #重定向到登录页
后端输入有效性校验:
class LoginForm(wtforms.Form):
username = wtforms.StringField(validators=[Length(min=3, max=20, message="用户名格式错误!")])
password = wtforms.StringField(validators=[Length(min=6, max=20, message="密码格式错误!")])
后端用户信息校验后的不同情况如下讨论所示。
2.2.1 用户信息校验成功跳转到个人主页
个人主页前端代码:
{% extends "base.html" %}
{% block title %}Index{% endblock %}
{% block head %}
<link rel="stylesheet" href="{{ url_for('static', filename='css/basecss.css') }}">
{% endblock %}
{% block content %}
<div class="post">
<div class="user"><img src="{{ url_for('static', filename='img/user1.jpg') }}" class="userimg">user1</div>
<div class="postcontent"><img src="{{ url_for('static', filename='img/img1.jpg') }}" class="postimg"></div>
</div>
<div class="post">
<div class="user"><img src="{{ url_for('static', filename='img/user2.jpg') }}" class="userimg">user2</div>
<div class="postcontent"><img src="{{ url_for('static', filename='img/img2.jpg') }}" class="postimg"></div>
</div>
<div class="post">
<div class="user"><img src="{{ url_for('static', filename='img/user3.jpg') }}" class="userimg">user3</div>
<div class="postcontent"><img src="{{ url_for('static', filename='img/img3.jpg') }}" class="postimg"></div>
</div>
{% endblock %}
个人主页视图函数:
@bp.route('/index')
def index():
return render_template('index.html')
效果如下:
输入已注册的用户名与正确的密码:
跳转到个人主页:
2.2.2 用户存在但密码错误
后端反馈错误(仅截取相关部分代码):
else: # 密码不正确
print("用户名或密码错误!")
var1 = '用户名或密码错误!'
return render_template("login.html", lof_errors=var1) # 返回错误信息到前端页面
前端接受错误信息并显示(仅截取相关部分代码):
{% if lof_errors == '用户名或密码错误!' %} <!--后端校验内容-->
<script type="text/javascript">alert("用户名或密码错误!")</script>
{% endif %}
效果如下:
输入已注册的用户名但错误的密码:
弹窗提示错误信息:
2.2.3 用户不存在(未注册)跳转到注册页
注册页面前端代码(HTML):
{% extends "base.html" %}
{% block title %}Register{% endblock %}
{% block head %}
<link rel="stylesheet" href="{{ url_for('static', filename='css/register.css') }}">
<script src="{{ url_for('static', filename='jquery/jquery.3.6.min.js') }}"></script>
<script src="{{ url_for('static', filename='js/register.js') }}"></script>
{% endblock %}
{% block content %}
<form method="POST">
<div class="form-group">
<div class="loginformlabel"><label>邮箱</label></div>
<input type="email" class="form-control" id="exampleInputEmail1" aria-describedby="emailHelp" name="email">
</div>
<div class="form-group">
<div class="loginformlabel"><label>验证码</label></div>
<div class="input-group">
<input type="text" id="yanzm" name="captcha">
<button class="btnyzm" type="button" id="captcha-btn">获取验证码</button>
</div>
</div>
<div class="form-group">
<div class="loginformlabel"><label>用户名</label></div>
<input type="text" class="form-control" name="username">
</div>
<div class="form-group">
<div class="loginformlabel"><label>密码</label></div>
<input type="password" class="form-control" id="exampleInputPassword1" name="password">
</div>
<div class="form-group">
<div class="loginformlabel"><label>确认密码</label></div>
<input type="password" class="form-control" name="password_confirm">
</div>
<button type="submit" class="registerbutton" id="regibtn">立即注册</button>
</form>
{% endblock %}
注册页面视图函数:
@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
user = UserModel(email=email, username=username, password=generate_password_hash(password))
db.session.add(user)
db.session.commit()
return redirect(url_for("auth.login")) # 注册成功,跳转到登录页登录
else:
print(type(form.errors['email'])) # 校验失败,需重新填写信息
return redirect(url_for("auth.register"))
后端注册表单校验:
class RegisterForm(wtforms.Form):
# 注册表单输入有效性验证
email = wtforms.StringField(validators=[Email(message="邮箱格式错误!")])
captcha = wtforms.StringField(validators=[Length(min=4, max=4, message="验证码格式错误!")])
username = wtforms.StringField(validators=[Length(min=3, max=20, message="用户名格式错误!")])
password = wtforms.StringField(validators=[Length(min=6, max=20, message="密码格式错误!")])
password_confirm = wtforms.StringField(validators=[EqualTo("password")])
# 验证邮箱是否已被注册
def validate_email(self, field):
email = field.data
user = UserModel.query.filter_by(email=email).first()
if user:
raise wtforms.ValidationError(message="该邮箱已被注册!")
# 验证输入的验证码是否正确
def validate_captcha(self, field):
captcha = field.data
email = self.email.data
captcha_model = EmailCaptchaModel.query.filter_by(email=email, captcha=captcha).first()
if not captcha_model:
raise wtforms.ValidationError(message="邮箱或验证码错误!")
验证码相关:
后端视图函数代码(发送验证码):
@bp.route('/captcha/email')
def get_email_captcha():
email = request.args.get("email") # 获取输入的邮箱
source = string.digits*4
# 从source中随机取样,取四位
captcha = random.sample(source, 4)
captcha = "".join(captcha) # 把随机生成的四位数的列表转换成字符串
message = Message(subject="注册验证码", recipients=[email], body=f"您的验证码是{captcha}")
mail.send(message) # 向邮箱发送验证码
# 将邮箱与验证码信息添加到数据库中
email_captcha = EmailCaptchaModel(email=email, captcha=captcha)
db.session.add(email_captcha)
db.session.commit()
print(captcha)
return jsonify({"code": 200, "message": "", "data": None}) # 返回表示发送成功的状态码
前端“获取验证码”的JS代码:
$(function () {
$("#captcha-btn").click(function (event) { //按钮“获取验证码”的点击事件
event.preventDefault();
var email = $("#exampleInputEmail1").val(); //获取输入的邮箱
$.ajax({ //发送验证码
url: "/captcha/email?email="+email,
method: "GET",
success: function (result){
var code = result['code'];
if(code == 200){ //检查状态码
alert("邮箱验证码发送成功!");
}else{
alert(result['message']);
}
},
fail: function(error){
console.log(error);
}
})
});
});
效果如下:
输入邮箱,点击按钮“获取验证码”:
邮箱收到验证码,并查看数据库的数据:
输入收到的验证码以及其它信息,点击“立即注册”:
注册成功,跳转到登录页。
查看数据库中用户信息表:
即已注册成功,注册功能实现。
以上即为本次作业的全部内容。✅