【8.0】Flask框架之g对象和蓝图

发布时间 2023-08-26 21:47:26作者: Chimengmeng

【一】g对象

【1】引入

  • 请求来了,在request中放个path,后续的视图函数中都能拿到
  • flask不建议向request对象中放变量,建议使用g对象
    • g对象,当次请求中放入的变量,在当次请求中一直存在
    • global的缩写,global
  • 在Flask中,当我们处理请求时,有时需要在多个视图函数之间共享某些变量。
    • 通常情况下,我们不建议直接将这些变量存储在Flask的request对象中,而是建议使用g对象。
  • g对象是一种上下文全局对象,它可以在当前请求中存储变量,并在整个请求处理过程中保持一致。
    • g表示global(全局)的缩写,它是Flask提供的一种轻量级的数据共享方式。

【2】使用

from flask import Flask, g, request

app = Flask(__name__)
app.debug = True

@app.before_request
def before_request_func():
    if request.path == '/':
        g.path = "g_path"

def test_path():
    print('test_path :>>>', g.path)

@app.route('/', methods=['GET', 'POST'])
def index():
    print(g.path)
    # 输出:g_path
    test_path()
    # 输出:test_path :>>> g_path
    return 'index'

@app.route('/home', methods=['GET', 'POST'])
def home():
    print(g.path)
    # 报错:AttributeError: path
    # 报错原因:g对象只在当前请求对象中生效
    # 在g对象的逻辑中,只对根路径生效
    test_path()
    return 'home'

if __name__ == '__main__':
    app.run()
  • 在上面的示例中,我们使用了before_request装饰器来注册一个函数,在每个请求到来之前被调用。
    • 在这个函数中,我们检查当前请求的路径是否为根路径'/',如果是的话,我们将一个变量path存储到g对象中。
  • 在视图函数index()中,我们可以直接访问g.path来获取之前存储的路径变量,并打印它。
  • 此外,还演示了如何在测试函数test_path()中使用g对象中的变量。
  • 需要注意的是,当我们在视图函数home()中访问g.path时,会抛出AttributeError: path的异常。
    • 这是因为g对象中存储的变量只在当前请求对象中生效,并且在g对象的逻辑中,仅对根路径生效。

【二】蓝图

  • 蓝图(blueprint):
    • flask都写在一个文件中,项目这样肯定不行,分目录,分包,使用蓝图划分目录

【1】不使用蓝图,自己分文件

  • 目录结构
-templates
-views
	-__init__.py
    -user.py
    -order.py
-app.py
  • app.py
from views import app
if __name__ == '__main__':
    app.run()
  • init.py
from flask import Flask,request
app = Flask(__name__)
#不导入这个不行
from . import account
from . import order
from . import user
  • user.py
from . import app
@app.route('/user')
def user():
    return 'user'
  • order.py
from . import app
@app.route('/order')
def order():
    return 'order'

【2】使用蓝图之中小型系统

  • 目录结构
-flask_pro				#  项目名
	-flask_test			# 核心文件
    	-__init__.py	# 包的inin里面实例化得到app对象
    	-static			# 静态文件
        -templates		# 模板
        -views			# 视图函数,类
        	-order.py
            -user.py
     -manage.py 		# 启动文件
  • __init__.py
from flask import  Flask
app=Flask(__name__)
from flask_test.views import user
from flask_test.views import order
app.register_blueprint(user.us)
app.register_blueprint(order.ord)
  • manage.py
from flask_test import  app
if __name__ == '__main__':
    app.run(port=8008)
  • user.py
from flask import Blueprint
us=Blueprint('user',__name__)

@us.route('/login')
def login():
    return 'login'
  • order.py
from flask import Blueprint
ord=Blueprint('order',__name__)

@ord.route('/test')
def test():
    return 'order test'
  • 使用蓝图注册路由步骤
    • 实例化得到一个蓝图对象
      • order_blue=Blueprint('order',__name__,template_folder='../templates')
    • 以后注册路由,写请求扩展,都使用蓝图
      • @user_blue.before_request
      • @user_blue.route('/register')
    • 在app中注册蓝图
      • from . import user
      • app.register_blueprint(user.user_blue)
      • app.register_blueprint(user.user_blue,url_prefix='/user')

【3】使用蓝图之大型系统

【4】小结

  • 1 xxx = Blueprint('account', name,url_prefix='/xxx') :蓝图URL前缀,表示url的前缀,在该蓝图下所有url都加前缀
  • 2 xxx = Blueprint('account', name,url_prefix='/xxx',template_folder='tpls'):给当前蓝图单独使用templates,向上查找,当前找不到,会找总templates
  • 3 蓝图的befort_request,对当前蓝图有效
  • 4 大型项目,可以模拟出类似于django中app的概念

【补充】

  • 在Flask中,蓝图(Blueprint)是一种组织和管理路由、视图函数以及静态文件等的方式。它允许将应用程序拆分为多个模块,并使其更加可维护和可扩展。

【1】不使用蓝图,自己分文件

  • 当应用程序规模较小或功能较简单时,可以不使用蓝图,而是直接将所有的路由、视图函数和静态文件集中在一个文件中。
    • 这种方式适合于具有较少功能和路由的小型应用程序。
  • 例如,下面是一个简单的Flask应用程序示例,其中不使用蓝图:
from flask import Flask, render_template

app = Flask(__name__)

@app.route("/")
def index():
    return render_template("index.html")

@app.route("/about")
def about():
    return render_template("about.html")

if __name__ == "__main__":
    app.run()
  • 在这个示例中,所有的路由和视图函数都定义在同一个文件中。
  • 这种方式适合于简单的网站或小型系统,但当应用程序逐渐增长并且具有更多的功能时,维护起来可能会变得困难。

【2】使用蓝图之中小型系统

  • 在一个中小型系统中,使用蓝图可以更好地组织代码,提高可维护性和可读性。
  • 可以将不同功能模块的路由和视图函数分别定义在不同的蓝图中,然后将这些蓝图注册到应用程序上。
  • 例如,下面是一个使用蓝图的Flask应用程序示例:
from flask import Flask, Blueprint, render_template

app = Flask(__name__)

main_bp = Blueprint("main", __name__)
admin_bp = Blueprint("admin", __name__)

@main_bp.route("/")
def index():
    return render_template("index.html")

@main_bp.route("/about")
def about():
    return render_template("about.html")

@admin_bp.route("/admin/dashboard")
def dashboard():
    return render_template("dashboard.html")

app.register_blueprint(main_bp)
app.register_blueprint(admin_bp, url_prefix="/admin")

if __name__ == "__main__":
    app.run()
  • 在这个示例中,main_bpadmin_bp分别代表主要功能和管理员功能的蓝图。
  • 通过使用蓝图,可以将主要功能和管理员功能的路由和视图函数分开管理。
  • 同时,url_prefix参数可以指定管理员功能的URL前缀为"/admin"。

【3】使用蓝图之大型系统

  • 在大型系统中,使用蓝图是必不可少的,可以将整个应用程序拆分成多个模块,每个模块都有自己独立的蓝图来管理路由和视图函数。

  • 例如,一个电子商务网站可以将用户相关功能、商品相关功能、订单相关功能等拆分成不同的蓝图,并按照功能模块来注册和管理。

from flask import Flask, Blueprint, render_template

app = Flask(__name__)

user_bp = Blueprint("user", __name__)
product_bp = Blueprint("product", __name__)
order_bp = Blueprint("order", __name__)

# 在这里定义用户模块的路由和视图函数
@user_bp.route("/")
def index():
    return render_template("index.html")

# 在这里定义商品模块的路由和视图函数
@product_bp.route("/")
def products():
    return render_template("products.html")

# 在这里定义订单模块的路由和视图函数
@order_bp.route("/")
def orders():
    return render_template("orders.html")

app.register_blueprint(user_bp, url_prefix="/user")
app.register_blueprint(product_bp, url_prefix="/product")
app.register_blueprint(order_bp, url_prefix="/order")

if __name__ == "__main__":
    app.run()
  • 在这个示例中,使用了user_bpproduct_bporder_bp等蓝图来管理不同功能模块的路由和视图函数。
    • 同时,使用了url_prefix参数来为每个蓝图指定URL前缀。
  • 通过使用蓝图,可以将大型系统按照功能模块拆分并进行管理,使得代码更加清晰、可维护性更高,并且方便团队协作开发。