当前位置: 首页 > news >正文

Flask----前后端不分离-登录

文章目录

  • 扩展模块
  • 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 BaseConfigapp = 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 EqualToclass 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  GETreturn 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 dbclass UserModel(db.Model):__tablename__ = "user_t"# 必须设定主键id = db.Column(db.Integer, primary_key=True, autoincrement=True)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 

 

注册与登录

将注册登录的后端逻辑迁移到指定的模块,窗口routers目录及routers.py模块,仅为了便于管理路由与视图。
routers/routers.py 路由与视图函数:

# __author__ = "laufing"
# 注册路由与视图
from app import app, RegForm, LoginForm, db
from flask import request, session, render_template, send_file  # request & session 请求上下文对象
from models.user_models import UserModel
from werkzeug.security import generate_password_hash, check_password_hash@app.route("/user/reg", methods=["GET", "POST"])  # 必须从/开始
def reg():if request.method == "GET":# 实例化表单对象form_obj = RegForm()# 渲染注册页面render_template("reg.html", form_obj=form_obj)# 实例化表单,接收request.form里的数据reg_form = RegForm()if reg_form.validate_on_submit():  # 验证通过# 保存用户的注册信息user = UserModel(uname=reg_form.uname.data, password=generate_password_hash(reg_form.passwd.data))# 通过会话保存db.session.add(user)db.session.commit()# 返回登录页面login_form = LoginForm()return render_template("login.html", form_obj=login_form)# 返回错误信息return render_template("reg.html", form_obj=reg_form)@app.route("/user/login", methods=["GET", "POST"])  # 必须从/开始
def login():if request.method == "GET":# 实例化表单对象form_obj = LoginForm()# 渲染注册页面render_template("login.html", form_obj=form_obj)# 实例化表单,接收request.form里的数据login_form = LoginForm()if login_form.validate_on_submit():  # 验证通过# 验证用户的信息uname = login_form.uname.datapasswd = login_form.passwd.data# 查询用户user = UserModel.query.filter_by(uname=uname).first()if user and check_password_hash(user.password, passwd):print("登录成功:", login_form.uname.data)# 会话保持session["uname"] = user.uname# 返回首页return render_template("index.html")else:login_form.custom_error = ["用户名或者密码错误"]return render_template("login.html", form_obj=login_form)# 返回错误信息return render_template("login.html", form_obj=login_form)

 

会话保持

session

 
flask-session

 

flask-login实现登录、登出

pending…


http://www.mrgr.cn/news/83413.html

相关文章:

  • 腾讯云下架印度云服务器节点,印度云服务器租用何去何从
  • 多跳问答中的语言模型知识编辑增强
  • 解决el-table表格数据量过大导致页面卡顿问题 又名《umy-ui---虚拟表格仅渲染可视区域dom的神》
  • Java Web开发进阶——Spring Boot与Spring Data JPA
  • Azure主机windows2008就地升级十步
  • 汽车免拆诊断 | 2007款保时捷Carrera S车行驶中发动机冷却液温度报警灯异常点亮
  • 【算法与数据结构】—— 回文问题
  • 有心力场的两体问题
  • 修改之前的代码使得利用设备树文件和Platform总线设备驱动实现对多个LED的驱动【只是假想对LED进行驱动,并没有实际的硬件操作】
  • 大模型WebUI:Gradio全解11——Chatbots:融合大模型的多模态聊天机器人(2)
  • android四大组件之一——Service
  • 探索 C++ Insights: 理解编译器背后的 C++ 实现
  • 树的模拟实现
  • python 个人学习笔记
  • RabbitMQ基础(简单易懂)
  • day06_Spark SQL
  • 【源码解析】Java NIO 包中的 ByteBuffer
  • 【Rust自学】11.7. 按测试的名称运行测试
  • Python|基于DeepSeek大模型,实现文本内容仿写(8)
  • MySql按年月日自动创建分区存储过程
  • 使用Struts2遇到的Context[项目名称]启动失败问题解决(Java Web学习笔记)
  • 《CPython Internals》阅读笔记:p96-p96
  • 20、Citrix 云桌面常见VDA注册问题汇总
  • HTTP 核心概念
  • 10.STM32F407ZGT6-内部温度传感器
  • 【论文+源码】一个基于Vue.js的MOBA类游戏攻略分享平台