Flask基础(3):session、flash、特殊装饰器、蓝图、路由正则匹配、上下文管理 & flask-session

Session:

Flask 默认将 session 以加密的形式放到了浏览器的 cookie 中
Flask 的 session 就是一个字典,字典有什么方法 session 就有什么方法
flask session 原理:当请求刚进来时,flask会读取cookie中 session(配置文件中能改这个名称) 对应的值,将这个值解密并反序列化成为一个字典放入内存,
                    以便视图函数使用;
                    在视图函数中使用时,按照字典的方法使用;
                    当请求结束时,flask会读取内存中字典的值,进行序列化+加密,然后再写入到用户的 cookie 中

flash:

# flash 是 取一次就没有;基于 session 实现的
# 原理:在 session 中存储一个数据,读取时通过 pop 将数据移除,从而达到只能取一次的效果
from flash import get_flashed_messages
flash("临时数据存储","error")  # 存 flash;"error" 表示分类
get_flashed_messages()   # 取 flash 中的值;列表的形式; get_flashed_messages(category_filter=["error"]) 表示根据 分类取 flash

特殊装饰器:(重点)

  **1. @app.before_request  # 所有请求之前进行的操作;被装饰的函数没有 参数 和 返回值;作用类似于 Django 的 process_request
    2. @app.template_global()  # 给模板用的
    3. @app.template_filter()  # 给模板用的

  **4. @app.after_request  # 被装饰的函数要有 参数 和 返回值;作用类似于 Django 的 process_response

        @app.after_request
        def test(response):
            print("after_request")
            return response
    # 对于有多个 @app.before_request ,谁先定义谁先执行;对于有多个 @app.after_request ,谁先定义谁后执行;类似于 Django 中间件的执行顺序

    # 对于 before_request,可以在定义自己逻辑时添加返回值,这样就不会执行后面的 before_request 和 视图,但还会执行所有的 after_request;这是和 Django(1.10以后版本不一样的地方)

    5. @app.before_first_request  # 只有第一次请求才执行
    6. @app.errorhandler(错误码)  # 报错的时候执行的函数;可用于定制错误信息(页面)

        @app.errorhandler(404)
        def not_found(arg): # arg 是错误信息
            print(arg)
            return "没找到"

Blueprint:蓝图

示例目录:

crm
|---crm
    |--- __init__.py  # 实例化 Flask 等等
    |---views
        |---account.py
        |---user.py
|---manage.py  # 入口函数

manage.py

from crm import create_app

app = create_app()  

if __name__ == ‘__main__‘:
    app.run()  # 运行 Flask 的实例

crm/__init__.py

from flask import Flask
from .views.account import ac
from .views.user import uc

def create_app():

    app = Flask(__name__)

    # @app.before_request   # 全局性的 before_request
    # def x1():
    #     print(‘app.before_request‘)

    app.register_blueprint(ac)
    app.register_blueprint(uc,url_prefix=‘/api‘)  # 给 uc 这个蓝图的 url 添加一个 前缀
    return app

crm/views/account.py

from flask import Blueprint,render_template

ac = Blueprint(‘ac‘,__name__)  # 实例化一个蓝图

@ac.before_request  # 只给 ac 这个蓝图添加 before_request
def x1():
    print(‘app.before_request‘)

@ac.route(‘/login‘)
def login():
    return render_template(‘login.html‘)

@ac.route(‘/logout‘)
def logout():
    return ‘Logout‘

crm/views/user.py

from flask import Blueprint

uc = Blueprint(‘uc‘,__name__)

@uc.route(‘/list‘)
def list():
    return ‘List‘

@uc.route(‘/detail‘)
def detail():
    return ‘detail‘

蓝图的作用:

1. 目录结构的划分
2. 路径加前缀
3. 给某些应用(视图)加装饰器

路由的正则匹配:

# 1. 先定义一个类: RegexConverter(BaseConverter)
# 2. app.url_map.converters["reg"] = RegexConverter
# 3. 用户发送请求
# 4. 使用自定义正则:
    @app.route("/index/<reg(‘\d+‘):nid>")
    def index(nid):
        print(nid,type(nid)
        print(url_for(‘index‘,nid=987)  # 返回生成url时,自动触发 RegexConverter 的 to_url 方法
# 4. flask内部进行正则匹配
# 5. to_python 方法的返回值会交给视图函数的参数

上下文管理:

1. request
2. session  # 注: Flask 默认将 session 以加密的形式放到了浏览器的 cookie 里面
3. app
4. g

请求--视图--响应 大致流程:

请求到来时:
    # ctx = RequestContext(self,environ)  # self 是 app对象,environ表示请求相关的原始数据
    # ctx.request = Request(environ)
    # ctx.session = None

    # 将包含了 request和session 的ctx对象打包放到某个地方(相当于一个大字典;根据线程或协程加个唯一标识,放进去的,所以数据相互隔离)
        {
            1232:{ctx:ctx对象},
            ...
        }
视图函数:
    from flask import request,session
    # 上述代码背后的过程:根据当前线程或者协程的唯一标识,取到 ctx对象,然后取到 request和session
请求结束:
    根据当前线程的唯一标识,将 大字典 中该线程对应的数据移除

上下文管理--request:

# 1. wsgi:初步处理请求
# 2. __call__ 方法 --> wsgi_app 方法
# 3. wsgi_app方法:
        ctx = RequestContext(session,request)
        ctx.push()
# 4. LocalStack:把 ctx 对象添加到 Local 中 (LocalStack起到一个中介的作用;视图函数取值时也是来 LocalStack 中取值,而不能直接去 Local 中取)
# 5. Local:为每个线程或协程开辟一块相互隔离的内存空间; local对象中有一个 __storage__ 的字典
        __storage__ = {
            线程/协程唯一标识:{"stack":[ctx对象(request和session),]}
        }

上下文管理--session:

# 通过 LocalStack 获取 ctx 中的 session,给 session 赋值(从 cookie 中读取数据,进行解密和反序列化;调用 open_session() 方法)

补充:

# Flask 和 Django 对比:
    相同点:都是基于 wsgi 协议写的
    最大不同点:request的机制不同:请求相关的数据,对于Django是通过参数传递一个一个传递过来的;flask是把请求相关的数据放到“一个地方”(大字典),以后就来这里取对应的数据

# 全局变量只有在初次加载时执行
# 类中的 __slots__() 的作用:在类外面只有 ()中的属性能通过 . 获取到,如: __slots__("name") ,只能获取到 obj.name

flask-session:

# Flask 第三方组件--flask-session:可将 session 保存到 redis 中

安装:

pip install flask-session  

使用:

import redis
from flask import Flask,request
from flask_session import Session  # 导入 flask-session 中的 Session

app = Flask(__name__)

app.config["SESSION_TYPE"] = "redis"  # 3. 由下面的分析可知,配置文件中应该要先配置好 SESSION_TYPE; 此时 app.session_interface = RedisSessionInterface();RedisSessionInterface 中也有 open_session 和 save_session 这两个方法
app.config["SESSION_REDIS"] = redis.Redis(host="127.0.0.1",port=6379,password="")  # 4. 配置 session 的 Redis
# 通过这些操作, session 就会保存到 redis 中;此时保存在 浏览器中的 cookie 是一个 随机字符串(uuid.uuid4()),当请求到达时 通过这个 cookie(随机字符串)来 redis 中取 session

# 1. flask 默认的 session 处理是通过 app.session_interface = SecureCookieSessionInterface()
Session(app)
# 2. app 经过 Session 实例化之后,app.session_interface = self._get_interface(app) ; session 保存到哪和 配置文件中的 "SESSION_TYPE" 有关

pass 

原文地址:https://www.cnblogs.com/neozheng/p/10150644.html

时间: 2024-09-30 21:16:40

Flask基础(3):session、flash、特殊装饰器、蓝图、路由正则匹配、上下文管理 & flask-session的相关文章

Flask上下文管理、session原理和全局g对象

一.一些python的知识 1.偏函数 def add(x, y, z): print(x + y + z) # 原本的写法:x,y,z可以传任意数字 add(1,2,3) # 如果我要实现一个功能,这三个数中,其中一个数必须是3 # 我们就可以使用偏函数来帮着我们传参 from functools import partial # partial:给add这个函数固定传一个数字 3 new_add = partial(add, 3) # 因此新的函数只需要传2个参数 new_add(1,1)

Python开发基础-Day7-闭包函数和装饰器基础

补充:全局变量声明及局部变量引用 python引用变量的顺序: 当前作用域局部变量->外层作用域变量->当前模块中的全局变量->python内置变量 global关键字用来在函数或其他局部作用域中使用全局变量,声明后可以在其他作用于中修改和使用 x=1 #全局赋值变量 def foo(): global x #函数内部全局声明变量x x=1111111 #函数内部修改全局变量x print(x) foo() print(x) global声明的变量在任何作用域都能够修改,所以一般非必要情

Flask之基于route装饰器的路由系统(源码阅读解析)

一 路由系统 1. 在flask中配置URL和视图函数的路由时,首先需要在main.py中实例化一个app对象: 1 from flask import Flask, render_template 2 3 app = Flask(__name__) 2. 然后通过app实例的route方法装饰视图函数,实现路由的配置: 1 @app.route('/') 2 def hello_world(): 3 return 'Hellow World!' 3. 所有这里需要关注在Flask类里定义的ro

python 基础篇 11 函数进阶----装饰器

11. 前??能-装饰器初识本节主要内容:1. 函数名的运?, 第?类对象2. 闭包3. 装饰器初识 一:函数名的运用: 函数名是一个变量,但他是一个特殊变量,加上括号可以执行函数. ?. 闭包什么是闭包? 闭包就是内层函数, 对外层函数(非全局)的变量的引?. 叫闭包 可以使用_clesure_检测函数是否是闭包  返回cell则是闭包,返回None则不是 闭包的好处: 由它我们可以引出闭包的好处. 由于我们在外界可以访问内部函数. 那这个时候内部函数访问的时间和时机就不?定了, 因为在外部,

Python-Day4 Python基础进阶之生成器/迭代器/装饰器/Json &amp; pickle 数据序列化

一.生成器 通过列表生成式,我们可以直接创建一个列表.但是,受到内存限制,列表容量肯定是有限的.而且,创建一个包含100万个元素的列表,不仅占用很大的存储空间,如果我们仅仅需要访问前面几个元素,那后面绝大多数元素占用的空间都白白浪费了.所以,如果列表元素可以按照某种算法推算出来,那我们是否可以在循环的过程中不断推算出后续的元素呢?这样就不必创建完整的list,从而节省大量的空间.在Python中,这种一边循环一边计算的机制,称为生成器:generator. 要创建一个generator,有很多种

Python基础(7)闭包函数、装饰器

一.闭包函数 闭包函数:1.函数内部定义函数,成为内部函数, 2.改内部函数包含对外部作用域,而不是对全局作用域名字的引用 那么该内部函数成为闭包函数 #最简单的无参闭包函数 def func1() name='ares' def func2() print(name) #有参和返回值的闭包函数 def timmer(func): def wrapper(*args,**kwargs): start_time = time.time() res=func(*args,**kwargs) stop

Python心得基础篇【10】装饰器

1 def outer(func): 2 def inner(*arg, **kwargs): 3 print('123') 4 ret = func(*arg, **kwargs) 5 print('112233') 6 return ret 7 return inner 8 9 10 def home(s1, s2): 11 return 'home' 12 13 14 def show(s1, ss): 15 return 'show' 16 17 @outer 18 def f1(arg

如何正确理解关键字&quot;with&quot;与上下文管理器(转载)

如果你有阅读源码的习惯,可能会看到一些优秀的代码经常出现带有 “with” 关键字的语句,它通常用在什么场景呢?今天就来说说 with 和 上下文管理器. 对于系统资源如文件.数据库连接.socket 而言,应用程序打开这些资源并执行完业务逻辑之后,必须做的一件事就是要关闭(断开)该资源. 比如 Python 程序打开一个文件,往文件中写内容,写完之后,就要关闭该文件,否则会出现什么情况呢?极端情况下会出现 “Too many open files” 的错误,因为系统允许你打开的最大文件数量是有

如何正确理解关键字&quot;with&quot;与上下文管理器

转自:https://foofish.net/with-and-context-manager.html 如果你有阅读源码的习惯,可能会看到一些优秀的代码经常出现带有 "with" 关键字的语句,它通常用在什么场景呢?今天就来说说 with 和 上下文管理器. 对于系统资源如文件.数据库连接.socket 而言,应用程序打开这些资源并执行完业务逻辑之后,必须做的一件事就是要关闭(断开)该资源. 比如 Python 程序打开一个文件,往文件中写内容,写完之后,就要关闭该文件,否则会出现什