文章目录
- 扩展模块
- flask-wtf 的简单使用
- 定义用户数据模型
- flask-login完成用户登录
扩展模块
- flask-sqlalchmy,连接数据库
- flask-login,处理用户的登录,认证
- flask-session,会话保持,默认对用户数据加密,存储在客户端浏览器的cookie中,每次请求时携带cookie来识别用户;也可以存储在服务端的文件、数据库、缓存中;
- flask-wtf 处理表单数据,防止csrf攻击;flask-wtf文档
flask-wtf 的简单使用
基于flask-wtf 制作简单的注册、登录页面;
- 注册页面
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>注册页面</title>
<script src="/static/js/index.js"></script>
<link rel="stylesheet" href="/static/css/index.css">
</head>
<body>
<form method="POST" action="/reg">
{{ form.csrf_token }}<br>
<h3>欢迎注册</h3><br>
{{ form.uname.label }} {{ form.uname(size=20) }}<br>
{{ form.passwd.label }} {{ form.passwd(size=20) }}<br>
{{ form.confirm_passwd.label }} {{ form.confirm_passwd(size=20)}}<br>
<input type="submit" value="登录">
{% if form.errors %}
<ul class="errors">
{% for error in form.errors %}
<li>{{ error }}字段验证未通过</li>
{% endfor %}
</ul>
{% endif %}
</form>
</body>
</html>
这里的form变量是flask渲染模板时,传入的表单对象。,form.csrf_token分别在表单中、cookie中生成一个秘钥,在提交表单时,cookie中的秘钥连同表单中的秘钥一同传给后端进行验证,验证通过则为合法的请求。
登录页面实现类似;
- flask后端定义表单子类、字段、验证器,app/_init_.py
# __author__ = "laufing"
import os
from flask import Flask
from .config import BaseConfig
app = Flask(__name__)
app.config.from_object(BaseConfig)
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
# 模板地址
app.template_folder = os.path.join(BASE_DIR, "templates")
# 静态资源地址
app.static_url_path = "/static/"
app.static_folder = os.path.join(BASE_DIR, "static")
# 导入表单
from flask_wtf import FlaskForm
# 导入字段
from wtforms import StringField, PasswordField, IntegerField, DateTimeField, BooleanField
from wtforms.validators import DataRequired, InputRequired # 必须输入
from wtforms.validators import EqualTo
class RegForm(FlaskForm):
uname = StringField("uname", validators=[InputRequired(), DataRequired()])
passwd = PasswordField("passwd", validators=[DataRequired(), InputRequired()])
confirm_passwd = PasswordField("confirm_passwd", validators=[EqualTo("passwd")])
class LoginForm(FlaskForm):
# 在服务端验证用户的输入
uname = StringField("uname", validators=[DataRequired(), InputRequired()])
passwd = PasswordField("passwd", validators=[DataRequired(), InputRequired()])
- flask后端定义视图,main.py
# __author__ = "laufing"
from app import app
from flask import render_template, jsonify, request, session, redirect, url_for
from app import LoginForm, RegForm
@app.route("/reg", methods=["GET", "POST"])
def register():
if request.method == "GET":
form = RegForm()
return render_template("reg.html", form=form) # 传入form对象渲染表单
form = RegForm() # 接收request.form 表单数据
if form.validate_on_submit():
# 保存用户的信息,待实现
return redirect('/login') # 重定向到 /login GET
return render_template("reg.html", form=form)
@app.route("/login", methods=["GET", "POST"])
def login():
if request.method == "GET": # 返回登录页面
return render_template("login.html", form=LoginForm())
# 实例化表单对象(自动接收request.form里的数据), 接收用户的登录数据
form = LoginForm()
# 按添加的验证器,进行验证数据 & 是否POST请求
if form.validate_on_submit():
print(form.uname.data)
print(form.passwd.data)
return jsonify({
"code": 200,
"msg": "登录成功"
})
# 验证未通过时,显示错误信息
return render_template("login.html", form=form)
if __name__ == '__main__':
app.run(host="localhost", port=5050, debug=True)
- 目录结构
定义用户数据模型
- 数据库mysql;
- 驱动 flask-sqlalchmy
- 迁移flask-migrate
- flask db init 初始化,生成迁移目录(仅一次);
- flask db migrate -m “描述”, 创建迁移脚本;
- flask db upgrade,应用迁移,创建数据库、表;
- flask db downgrade,降级
- flask db history,迁移历史
- 文件models/user_models.py
- 版本
- flask==2.0.3
- jinja2=3.1.1
- werkzeug == 2.0.3
- sqlalchemy==1.3
- flask-sqlalchemy==2.4.0
- pyjwt==2.0.0
- email-validator==1.0.5
- packaging==21.0
- flask-migrate==2.6.0
在窗口app对象的_init_.py文件中,添加如下:
from flask-sqlalchemy import SQLAlchemy
from flask-migrate import Migrate
# ...
db = SQLAlchemy()
db.init_app(app)
migrate = Migrate(app, db)
创建models目录/ user_models.py:
from app import db
class UserModel(db.Model):
__tablename__ = "user_t"
uname = db.Column(db.String(50), unique=True)
passwd = db.Column(db.String(64), unique=True)
def __repr__(self):
return self.uname
命令行下完成初始化、迁移:
flask db init
flask db migrate -m '生成迁移命令'
flask db upgrade