(二十五)Flask之MTVMVC架构模式Demo【重点:原生session使用及易错点!】

news/2024/4/24 5:50:47/

目录:

  • 每篇前言:
  • MTV&MVC
  • 构建一个基于MTV模式的Demo项目:
    • 蹦出一个问题:

每篇前言:

  • 🏆🏆作者介绍:【孤寒者】—CSDN全栈领域优质创作者、HDZ核心组成员、华为云享专家Python全栈领域博主、CSDN原力计划作者

  • 🔥🔥本文已收录于Flask框架从入门到实战专栏:《Flask框架从入门到实战》
  • 🔥🔥热门专栏推荐:《Python全栈系列教程》、《爬虫从入门到精通系列教程》、《爬虫进阶+实战系列教程》、《Scrapy框架从入门到实战》、《Flask框架从入门到实战》、《Django框架从入门到实战》、《Tornado框架从入门到实战》、《前端系列教程》。
  • 📝​📝本专栏面向广大程序猿,为的是大家都做到Python全栈技术从入门到精通,穿插有很多实战优化点。
  • 🎉🎉订阅专栏后可私聊进一千多人Python全栈交流群(手把手教学,问题解答); 进群可领取Python全栈教程视频 + 多得数不过来的计算机书籍:基础、Web、爬虫、数据分析、可视化、机器学习、深度学习、人工智能、算法、面试题等。
  • 🚀🚀加入我一起学习进步,一个人可以走的很快,一群人才能走的更远!

在这里插入图片描述

MTV&MVC

先来讲一下两种常见的软件架构模式——MTV和MVC~

它俩是用于组织和管理应用程序的不同组件和逻辑。通常用于开发Web应用程序和其他软件项目。

  1. MTV(Model-Template-View):
    • Model(模型):表示应用程序的数据和业务逻辑。它负责管理数据的存储、检索和处理,以及处理与数据相关的操作。
    • Template(模板):定义了应用程序用户界面的外观和结构,通常使用模板语言编写,将动态数据插入静态页面中。
    • View(视图):表示用户界面的逻辑部分,它从模型中获取数据并将其呈现到模板中,然后将结果发送给用户的浏览器。视图还可以处理用户的输入和用户界面的交互。

MTV模式是Django Web框架的一部分(但是这个模式也非常适合Flask),其中Model对应于数据模型,Template对应于模板文件,View对应于视图函数,这些组合在一起用于构建Web应用程序。

  1. 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):

在这里插入图片描述


http://www.ppmy.cn/news/1391259.html

相关文章

冲刺跑转长跑过程中,新茶饮品牌如何觅增量?

如今&#xff0c;新茶饮行业的发展日趋成熟&#xff0c;并通过资本动作、市场扩张等释放出相关信号。 比如&#xff0c;在资本动作上&#xff0c;IPO已成为新茶饮品牌发展的重要议程。可以看到&#xff0c;截至2023年2月&#xff0c;正在推进港交所IPO的新茶饮企业就有茶百道、…

如何快速搭建一个完整的vue2+element-ui的项目-二

技术细节-继续配置 提示&#xff1a;你以为这样就完了吗,其实还有很多东西需要我们自己手写的 例如&#xff1a; element-ui的配置样式重置配置src使用的配置elinst配置axios异步请求的二次封转配置语言国际化配置(这个看需求,我这里就不用配置了)vuex的配置mixins的配置开发环…

Learn OpenGL 19 几何着色器

几何着色器 在顶点和片段着色器之间有一个可选的几何着色器(Geometry Shader)&#xff0c;几何着色器的输入是一个图元&#xff08;如点或三角形&#xff09;的一组顶点。几何着色器可以在顶点发送到下一着色器阶段之前对它们随意变换。然而&#xff0c;几何着色器最有趣的地方…

Flask vs. Django:选择适合你的Web开发框架【第134篇—Flask vs. Django】

&#x1f47d;发现宝藏 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。【点击进入巨牛的人工智能学习网站】。 Flask vs. Django&#xff1a;选择适合你的Web开发框架 在选择一个适合你项目的Web开发框架…

美食杂志制作秘籍:引领潮流,引领味蕾

美食杂志是一种介绍美食文化、烹饪技巧和美食体验的杂志&#xff0c;通过精美的图片和生动的文字&#xff0c;向读者展示各种美食的魅力。那么&#xff0c;如何制作一本既美观又实用的美食杂志呢&#xff1f; 首先&#xff0c;你需要选择一款适合你的制作软件。比如FLBOOK在线制…

牛客NC196 编辑距离(一)【较难 DFS/DP,动态规划,样本对应模型 Java,Go,PHP】

题目 题目链接&#xff1a; https://www.nowcoder.com/practice/6a1483b5be1547b1acd7940f867be0da 思路 编辑距离问题 什么是两个字符串的编辑距离&#xff08;edit distance&#xff09;&#xff1f;给定字符串s1和s2&#xff0c;以及在s1上的如下操作&#xff1a;插入&…

python3GUI--qt仿暴风影音视频播放器By:PyQt5(附下载地址)

文章目录 一&#xff0e;前言二&#xff0e;环境1.开发环境2.打包环境3.运行环境 三&#xff0e;软件截图1.启动页2.视频播放3.音频播放4.其他1.托盘2.对话框 四&#xff0e;功能总览五&#xff0e;代码展示&心得1.UI设计2.如何防止卡顿3.如何自定义组件 五&#xff0e;思考…

19.C++20中的std::latch和std::barrier

文章目录 线程闩std::latch和线程卡std::barrier线程闩std::latch线程卡std::barrier的使用线程闩std::latch和线程卡std::barrier的区别reference 欢迎访问个人网络日志&#x1f339;&#x1f339;知行空间&#x1f339;&#x1f339; 线程闩std::latch和线程卡std::barrier …

PPT好看配色

放几个链接&#xff01;画图时候可以参考&#xff01;转自知乎 Color Hunt ColorDrop 中国色 Flat UI Colors Coolors

Java 根据IP获取IP地址信息(离线)

<!-- https://mvnrepository.com/artifact/org.lionsoul/ip2region --><dependency><groupId>org.lionsoul</groupId><artifactId>ip2region</artifactId><version>2.7.0</version></dependency> 地址&#xff1a;http…

谷歌seo网络营销需要什么条件?

现如今&#xff0c;想在谷歌seo搞网络营销&#xff0c;一支团队是必不可少的&#xff0c;哪怕个人精通所有能力&#xff0c;但个人的时间精力也是有限的&#xff0c;更何况这是在不停变化的网络时代&#xff0c;所以一个团队是必要的&#xff0c;这自然不能是普通的团队&#x…

std::shared_ptr与std::make_unique在类函数中的使用

在最近学习cartographer算法的时候&#xff0c;发现源码中大量的使用了std::shared_ptr与std::make_unique&#xff0c;对于这些东西之前不是很了解&#xff0c;为了更好的理解源代码&#xff0c;因此简单学习了一下这块内容的使用&#xff0c;在这里简单记个笔记。 std::shar…

Java Maven项目实现自动化部署到Docker上

前言 目前项目是采用docker部署的, 由于需要新增一个微服务,最终是实现自动推送到远程的docker上,所以就顺便记录一下操作步骤 服务器层面配置 开启 docker 所在服务器远程访问 # 1、修改docker配置文件 vim /lib/systemd/system/docker.service 在ExecStart后面加上&#xff…

基于SpringBoot和Vue的大学生租房系统的设计与实现

今天要和大家聊的是一款今天要和大家聊的是一款基于SpringBoot和Vue的大学生租房系统的设计与实现。 &#xff01;&#xff01;&#xff01; 有需要的小伙伴可以通过文章末尾名片咨询我哦&#xff01;&#xff01;&#xff01; &#x1f495;&#x1f495;作者&#xff1a;李同…

C# xaml框架以及Java的ORM介绍

c#有ASP.Net,.NET以及EF Core这几个重要的运行时和框架.分别用于web,应用以及数据库的ORM. 目前跨平台的有Avalonia UI,.Net MAUI以及Uno Platform,至于WPF等本身不是跨平台的,但可以依靠其他库实现跨平台.这里面Avalonia应该是认为bug比较少的. 当然目前最火的跨平台解决方案…

C++ 作业 24/3/14

1、成员函数版本实现算术运算符的重载&#xff1b;全局函数版本实现算术运算符的重载 #include <iostream>using namespace std;class Test {friend const Test operator-(const Test &L,const Test &R); private:int c;int n; public:Test(){}Test(int c,int n…

中文编程入门(Lua5.4.6中文版)第七章 Lua 字符串与模式

在网游的符文之地中&#xff0c;我们可以通过神秘的“字符串法术”来处理和操作一系列字符。以下是如何在Lua的魔法卷轴上施展这种法术&#xff1a; 字符串的表示与召唤&#xff1a; 在Lua的魔法治则中&#xff0c;你可以运用三种方式召唤出一串字符&#xff08;即字符串&…

java锁关键字sychronized

前置知识&#xff1a; 在HotSpot虚拟机中&#xff0c;对象在内存中存储可分为三块区域&#xff1a; 对象头&#xff1a;有MarkWord和Klass Word组成实例数据&#xff1a;里面主要是成员变量对齐填充&#xff1a;不是8的整数倍&#xff0c;则填充 CAS: Compare and Swap是Jav…

在DelayMS加入bsp_Idle,把单片机延时空闲利用起来

在单片机应用中&#xff0c;使用延时函数 DelayMS() 会导致程序在延时期间无法执行其他任务&#xff0c; 这可能影响系统对一些响应时间要求较高的任务的处理。 为了提高系统的响应速度和利用单片机的空闲时间&#xff0c;可以在延时函数中加入 bsp_Idle() 函数&#xff0c; 以…

day-25 两数相加

思路&#xff1a;因为两个数字是逆序的&#xff0c;所以只需将对应位置的值相加&#xff0c;有进位则进位&#xff0c;再将结果利用头插法存入一个新的链表 注意点&#xff1a;两个链表不一定一样长 code: /*** Definition for singly-linked list.* public class ListNode …