(二十五)Flask之MTVMVC架构模式Demo【重点:原生session使用及易错点!】
目录:
- 每篇前言:
- MTV&MVC
- 构建一个基于MTV模式的Demo项目:
- 蹦出一个问题:
每篇前言:
🏆🏆作者介绍:【孤寒者】—CSDN全栈领域优质创作者、HDZ核心组成员、华为云享专家Python全栈领域博主、CSDN原力计划作者
- 🔥🔥本文已收录于Flask框架从入门到实战专栏:《Flask框架从入门到实战》
- 🔥🔥热门专栏推荐:《Python全栈系列教程》、《爬虫从入门到精通系列教程》、《爬虫进阶+实战系列教程》、《Scrapy框架从入门到实战》、《Flask框架从入门到实战》、《Django框架从入门到实战》、《Tornado框架从入门到实战》、《前端系列教程》。
- 📝📝本专栏面向广大程序猿,为的是大家都做到Python全栈技术从入门到精通,穿插有很多实战优化点。
- 🎉🎉订阅专栏后可私聊进一千多人Python全栈交流群(手把手教学,问题解答); 进群可领取Python全栈教程视频 + 多得数不过来的计算机书籍:基础、Web、爬虫、数据分析、可视化、机器学习、深度学习、人工智能、算法、面试题等。
- 🚀🚀加入我一起学习进步,一个人可以走的很快,一群人才能走的更远!
![]()
MTV&MVC
先来讲一下两种常见的软件架构模式——MTV和MVC~
它俩是用于组织和管理应用程序的不同组件和逻辑。通常用于开发Web应用程序和其他软件项目。
- MTV(Model-Template-View):
- Model(模型):表示应用程序的数据和业务逻辑。它负责管理数据的存储、检索和处理,以及处理与数据相关的操作。
- Template(模板):定义了应用程序用户界面的外观和结构,通常使用模板语言编写,将动态数据插入静态页面中。
- View(视图):表示用户界面的逻辑部分,它从模型中获取数据并将其呈现到模板中,然后将结果发送给用户的浏览器。视图还可以处理用户的输入和用户界面的交互。
MTV模式是Django Web框架的一部分(但是这个模式也非常适合Flask),其中Model对应于数据模型,Template对应于模板文件,View对应于视图函数,这些组合在一起用于构建Web应用程序。
- MVC(Model-View-Controller):
- Model(模型):与MTV中的模型类似,负责应用程序的数据和业务逻辑。它处理数据的存储、检索和处理。
- View(视图):与MTV中的视图有些不同,它表示应用程序的用户界面,但不直接与模板相关。视图接收用户输入,处理它并与模型进行通信以更新数据。
- Controller(控制器):控制器是MVC的核心,它负责接收用户输入并根据输入调度视图和模型的操作。它决定如何响应用户的请求,并确保模型和视图之间的协同工作。
MVC模式通常在框架如Spring、Ruby on Rails等中使用,它的核心思想是分离数据处理、用户界面和控制流,以提高代码的可维护性和可扩展性。控制器充当用户输入的处理中心,调度模型和视图以完成所需的操作。
总的来说,MTV和MVC都是用于组织和管理应用程序代码的模式,它们有不同的实现方式,但目标都是分离关注点,以提高代码的可读性和可维护性。
一一对应:

Flask如果采用MVC架构的话,项目结构demo:

但是推荐在Flask中使用MTV架构模式,而且Flask中主流也是用这个:

构建一个基于MTV模式的Demo项目:

-
login.html:
<!DOCTYPE html> <html lang="en"> <head><meta charset="UTF-8"><title>用户登录</title> </head> <body> <form action="" method="post"><input type="text" name="user"><input type="text" name="pwd"><input type="submit" value="提交">{{msg}} </form> </body> </html> -
account.py:
from flask import Blueprint, render_template, request, session, redirect from uuid import uuid4account = Blueprint('account', __name__)@account.route('/login', methods=['GET', 'POST']) def login():if request.method == 'GET':return render_template('login.html')user = request.form.get('user')pwd = request.form.get('pwd')if user == 'GuHanZhe' and pwd == '123':uid = str(uuid4())session['user_info'] = {'id': uid, 'name': user}return redirect('/index')else:return render_template('login.html', msg='用户名获或密码错误') -
home.py:
from flask import Blueprint, sessionhome = Blueprint('home', __name__)@home.route('/index') def index():user_info = session.get('user_info')print(user_info)return 'Index'@home.route('/test') def test():return 'Test' -
__init__.py:from flask import Flask from .views import account from .views import homedef create_app():app = Flask(__name__)app.config.from_object('settings.DevelopmentConfig')app.register_blueprint(account.account)app.register_blueprint(home.home)return app -
manage.py:
from flask_stru import create_app app = create_app()if __name__ == '__main__':app.run() -
settings.py:
class Config(object):DEBUG = TrueSECRET_KEY = 'GuHanZheIsCool'class ProductionConfig(Config):passclass DevelopmentConfig(Config):passclass TestingConfig(Config):pass
运行manage.py文件,访问login登录(登录成功的话):

来看下源码,看看默认cookie过期时间是多久:
from flask.sessions import SecureCookieSessionInterface


可以看到注释中表示这个值默认是31天~而且我们可以设置这个值:

而这个参数生效的前提是session.permanent为True(默认就是为True);
如果设置为False,则关闭浏览器cookie就失效。

再看看源码设置cookie的(save_session)上面这一部分:
如果if成立就直接返回,客户端就不会存cookie了!

蹦出一个问题:

访问index接口是正常的,name修改成功:

但是如果访问test接口的话,就不正常了:

很容易想到,这个问题的原因是因为cookie修改后没有保存!
抛出答案,这是因为修改cookie的话,默认只有当第一层修改才会保存,而第二层、第三层等…都不会保存。
{user_info: {k1: 1, k2: 2}
}如果是第一层被修改会保存:
{user_info: {k1: 1, k2: 2},xxx :{'A': 5}
}
但是如果是第二层,第三层...修改不会保存:
{user_info: {k1: 1, k2: 2, k3: 3}
}
看源码分析这种问题的点源于何处:


斗胆翻译一下第一个箭头所指变量对应的注释部分:
“当数据发生变化时,将此标志设置为
True。仅跟踪会话字典本身;如果会话包含可变数据(例如嵌套的字典),则在修改该数据时必须手动将此标志设置为True。仅当此标志为True时,会话cookie才会写入响应中。”
进第一个父类:


调用on_update函数了就会给modified设为True。
所以:
session['user_info'] = 'abc' # session.__setitem__
session['user_info'][('name')]
第一行会修改,但是第二行是调用的__getitem__,而源码(上图)没有相关处理,所以不会保存。
解决方法:

再来看下源码(上面没有看完的部分):


进去看,因为设置了modified为True,所以这个should_set_cookie就为True,所以这个if就不成立,就继续往下执行。
不过这部分源码给了我们另一个方法,如果设置SESSION_REFRESH_EACH_REQUEST这个参数为True,每次请求session也都会修改(用这个方法解决):

而且推荐使用这个方法,推荐用这个的原因:
想象一个使用场景,如果用户登录一个网站,cookie设置的二十分钟失效,如果这个过程中用户一直没有做cookie相关的操作,那么20分钟后登录就失效了,但是如果这二十分钟用户一直在访问这个网站,是不应该让用户失效的。
如果设置了上述这个参数为True,就不会出现这种问题,
SESSION_REFRESH_EACH_REQUEST 的行为是在用户请求时将会话标记为“新的”(fresh),以确保它在每个请求之后都会被刷新。这意味着,无论用户是否刷新浏览器或进行其他操作,都会重置会话的过期时间。这是为了确保用户在与应用交互期间会话不会过期(过期时间会从用户刷新的时间重新往后计算)
Flask中使用的话,要在登录成功后设置一下permanent也为True(但是如果用flask-session就不用了,因为这个默认是为True):

相关文章:
(二十五)Flask之MTVMVC架构模式Demo【重点:原生session使用及易错点!】
目录: 每篇前言:MTV&MVC构建一个基于MTV模式的Demo项目:蹦出一个问题: 每篇前言: 🏆🏆作者介绍:【孤寒者】—CSDN全栈领域优质创作者、HDZ核心组成员、华为云享专家Python全栈领…...
[ C++ ] STL---list的使用指南
目录 list简介 list的常用接口 构造函数 赋值运算符重载 迭代器 容量相关接口 元素访问接口 修改相关接口 头插push_front() 头删pop_front() 尾插push_back() 尾删pop_back() insert() erase() list的迭代器失效 list简介 1. list是可以以O(1)的时间复杂度在任意…...
数据可视化-ECharts Html项目实战(2)
在之前的文章中,我们学习了如何创建简单的折线图,条形图,柱形图并实现动态触发,最大最小平均值。想了解的朋友可以查看这篇文章。同时,希望我的文章能帮助到你,如果觉得我的文章写的不错,请留下…...
【Network Management】DCM模块唤醒网络是主动唤醒还是被动唤醒
目录 前言 正文 1.CanNm的状态机分析 2.ComM的状态机分析 3.诊断报文唤醒网络知识扩展...
yum repolist命令的介绍
yum repolist 命令在基于 Red Hat 的 Linux 发行版中用于列出当前配置的 YUM 仓库中所有可用的软件包及其版本信息。这个命令会从本地缓存中获取软件包的索引信息,并显示所有软件包的名称和版本号,而不会实际安装或更新任何软件包。 具体来说,…...
【日志分析】Android 运营商名称显示优先级(AlphaTag/SPN)
规则说明 MTK平台的设计,优先级:(MD)CIEV > Eons > Nitz > xml 功能代码说明 【笔记】Android Telephony 漫游SPN显示定制(Roaming Alpha Tag)-CSDN博客 日志分析 关键字:lookupOpe…...
ocp考试是中文还是英文?ocp认证好考吗
ocp认证是中文还是英文考试ocp认证的考试常用语种是英文,除开英文之外还有日语等语种,但是目前没有中文(12c的时候有过中文考试),所以考生最好具有一定的英语水平再报名参加考试,ocp认证考试的形式为机试,考试的题型全…...
python问题:vscode切换环境,pip安装库网络错误,不使用anaconda安装库
python问题:vscode切换环境,pip安装库网络错误 vscode切换环境pip安装库网络错误 不使用anaconda安装库 记录一下遇见的python问题。 vscode切换环境 在vscode上面的搜索框输入 > select interpreter然后选择需要的环境。 pip安装库网络错误 用…...
理财第一课:炒股词典
文章目录 基础代码规则委比委差量比换手率市盈率市净率 短线操作散户亏钱的原因庄家分析炒股战法波浪理论其它 钱者,人生之大事,死生存亡之地,不可不察也。耕田之利,十倍;珠玉之赢,百倍;闹革命&…...
矩阵消元-MIT
文章目录 1. 行变换消元法,XA 左乘行变换 1. 行变换消元法,XA 左乘行变换 假设我们有一个方程组表示如下: x 2 y z 2 ; 3 x 8 y z 12 ; 4 y z 2 (1) x2yz2;\quad 3x8yz12;\quad4yz2\tag{1} x2yz2;3x8yz12;4yz2(1)矩阵表示如下: [ 1 2 1 3 8 1…...
基于nodejs+vue班级管理系统的设计与实现-flask-django-python-php
随着电子技术的普及和快速发展,线上管理系统被广泛的使用,有很多事业单位和商业机构都在实现电子信息化管理,班级管理系统也不例外,由比较传统的人工管理转向了电子化、信息化、系统化的管理。随着互联网技术的高速发展࿰…...
2024年起,游戏开发团队62%的从业人员使用AI智能技术
易采游戏网3月19日消息:游戏引擎制造商最新发布的《Unity》报告证实,近六成的全球游戏开发团队已在各个环节全面采用人工智能技术,以大幅提升生产效率并节约宝贵时间。 伴随着科技的快速发展,游戏开发领域逐渐转向借助人工智能技术…...
mysql 主从复制、读写分离、高可用
MySQL 的主从复制、读写分离和高可用性是数据库架构中常见的概念,它们旨在提高数据库的可靠性、性能和可扩展性。下面我将分别解释这三个概念: 1. MySQL 主从复制 主从复制 是 MySQL 中的一个功能,允许数据从一个 MySQL 数据库服务器&#…...
力扣爆刷第100天之hot100五连刷86-90
力扣爆刷第100天之hot100五连刷86-90 文章目录 力扣爆刷第100天之hot100五连刷86-90一、139. 单词拆分二、300. 最长递增子序列三、152. 乘积最大子数组四、416. 分割等和子集五、32. 最长有效括号 一、139. 单词拆分 题目链接:https://leetcode.cn/problems/word-…...
Sublime Text3 C/C++一键调试运行代码
minGW的系统环境配置: 使用的C/C编译器是minGW,点此进入官网链接,下载后需要在线安装,安装后需要将安装目录下的bin目录所在路径加入path环境变量。本菜鸡的电脑里安装了CodeBlocks,在CodeBlocks的安装目录下有MinGW&…...
robots协议详解:爬虫也要有边界感
随着互联网的迅猛发展,信息的获取变得越来越便捷,而网络爬虫(Spider)技术就是其中之一。网络爬虫是一种自动化程序,它能够遍历互联网上的网页,提取信息,用于各种用途,例如搜索引擎索引、数据挖掘、价格比较等。但是,爬虫技术虽然强大,但是也是一把双刃剑,在正当使用…...
C#面:简述 var 和 dynamic
var 关键字: var 关键字是在编译时进行类型推断的。也就是说,编译器会根据变量的初始化表达式来确定变量的类型,并在编译时将其替换为实际的类型。var 关键字只能用于局部变量,不能用于字段、方法参数或返回类型。var 关键字声明…...
S32 Design Studio PE工具配置DMA
工具配置 DMA位置跟设备不一样,在Referenced_components里面。 Configurations里面就默认配置就行 channels是比较重要的,一条信号传输用到一个通道。可以选择UART、ADC、CAN之类的,这里用在了SPI通讯里面。 生成代码 在 Generated_Code\dm…...
【Effective C++】36绝不重新定义继承而来的non-virtual 函数
例子如下: class B { public:void mf(); };class D : public B {};D x; // x是一个类型为D的对象 // 方式一 B* pB &x // 获得一个pB 指向 x pB->mf(); // 经由指针调用mf// 方式二 D* pD &x // 获得一个指针指向x pD->mf(); // 经由指针调用mf我…...
STM32-DMA数据转运
DMA进行转运的条件 1:开关控制,DMA_CMD必须使能2:传输计数器必须大于03:触发源必须有触发的信号...
AVR智能充电器PID控制程序(基于ATmega16/ATmega328)
一、系统硬件架构 1. 硬件连接方案 AVR ATmega16 ├── ADC0 (PC0) → 电池电压采样(分压电阻) ├── ADC1 (PC1) → 充电电流采样(分流电阻运放) ├── OC1A (PB1) → PWM输出 → MOSFET驱动 → 充电控制 ├── INT0 (PD2) →…...
手把手教你用Arduino Nano和SSD1306屏幕DIY一个晶体管测试仪(附完整代码和烧录避坑指南)
手把手教你用Arduino Nano和SSD1306屏幕DIY一个晶体管测试仪(附完整代码和烧录避坑指南) 在电子制作和维修领域,能够快速识别晶体管引脚和参数的测试工具至关重要。本文将带你用最常见的Arduino Nano开发板和廉价的SSD1306 OLED屏幕ÿ…...
百度网盘下载加速全攻略:3步解锁满速下载的免费开源方案
百度网盘下载加速全攻略:3步解锁满速下载的免费开源方案 【免费下载链接】baidupcs-web 项目地址: https://gitcode.com/gh_mirrors/ba/baidupcs-web 还在为百度网盘下载速度慢如蜗牛而烦恼吗?每次下载大文件都需要花费数小时甚至更长时间&#…...
从零搭建一个视频处理Demo:基于RKMEDIA的VENC/VDEC完整数据流(采集->编码->解码->显示)
从零搭建视频处理Demo:基于RKMEDIA的端到端数据流实战指南 当第一次接触瑞芯微平台的RKMEDIA框架时,很多开发者会被分散的模块和复杂的数据流搞得晕头转向。本文将带你从零开始,构建一个完整的"摄像头采集→编码存储→解码播放"视频…...
SDK转H5网页支付接口开发|支持URL跳转唤起App,Python与易语言双版本源码
温馨提示:文末有联系方式一、什么是SDK转H5支付 SDK转H5支付,是指将原本面向原生App的移动端SDK能力,适配封装为标准HTTP协议的网页支付链接(即H5支付URL),使用户在浏览器或WebView中点击即可跳转至收银台完…...
微信读书笔记如何优雅地融入Obsidian知识库?
微信读书笔记如何优雅地融入Obsidian知识库? 【免费下载链接】obsidian-weread-plugin Obsidian Weread Plugin is a plugin to sync Weread(微信读书) hightlights and annotations into your Obsidian Vault. 项目地址: https://gitcode.com/gh_mirrors/ob/obsi…...
LabVIEW条件禁用结构实战:一招搞定跨平台(Windows/Linux)和不同环境的代码部署
LabVIEW条件禁用结构实战:跨平台与环境适配的工程级解决方案 在工业自动化领域,工程师们经常面临一个棘手问题:如何让同一套LabVIEW程序无缝运行在Windows工控机、Linux实时系统、嵌入式硬件等多种平台上?传统解决方案往往需要维护…...
为什么92%的Dify集成项目卡在身份认证?OAuth2.1+JWT双向透传实操详解(含Postman调试包)
第一章:为什么92%的Dify集成项目卡在身份认证?Dify 提供了强大的低代码 LLM 应用编排能力,但生产环境中近九成集成失败案例均源于身份认证环节——并非功能缺失,而是开发者对 Dify 的多层认证模型理解存在系统性偏差。Dify 同时支…...
黑苹果终极实战指南:OpenCore长期维护机型EFI深度解密
黑苹果终极实战指南:OpenCore长期维护机型EFI深度解密 【免费下载链接】Hackintosh Hackintosh long-term maintenance model EFI and installation tutorial 项目地址: https://gitcode.com/gh_mirrors/ha/Hackintosh 还在为苹果电脑的高昂价格望而却步&…...
别再手动翻官网了!用Python脚本自动爬取CKEditor历史漏洞与安全更新(附完整代码)
高效获取CKEditor安全情报:Python自动化爬虫实战指南 每次安全审计前,团队总要花几小时手动翻找CKEditor的漏洞公告?作为经历过这种低效工作模式的安全工程师,我开发了一套自动化解决方案。这个工具不仅能抓取所有历史漏洞&#x…...
