flask-蓝图、g对象

发布时间 2023-04-04 18:33:54作者: ERROR404Notfound

1.蓝图的使用

蓝图是由blueprint翻译过来的,作用是之前在一个py文件中写的flask项目,后期划分目录,不用蓝图同样可以划分项目

1.1 不用蓝图划分项目

不使用蓝图划分也可以完成项目需求,但是随着项目深入导入情况越来越多可能会出现导入错误
1.项目目录结构:
根目录:
src
init.py
models.py
views.py
static
templates
home.html
manage.py
image
2.项目代码
src/init.py

from flask import Flask

'''在src/__init__中拿到了app对象,templates和static在上一层,使用相对导入'''
app = Flask(__name__, template_folder='../templates', static_folder='../static')
app.debug = True
'''使用session需要加secret_key'''
app.secret_key='ruyt738yfuir6t'
'''manage.py中只导入了__init__中的内容,如果不把views放在这里,那么views中的代码就始终无法执行'''
from . import views
'''并且只能放在app产生之后,如果这行代码放在最上面app还没生成就开始使用,会报错'''

src/views.py:

from . import app
from flask import render_template

@app.route('/')
def index():
    return 'index'

@app.route('/home')
def home():
    return render_template('home.html',name='max')

src/models.py:

#  这里以后写表模型代码

templates/home.html:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <h1>home页面</h1>
    <h2>{{name}}</h2>
</body>
</html>

manage.py:

from src import app

if __name__ == '__main__':
    app.run()

image
image

1.2 使用蓝图划分项目

1.蓝图的使用步骤:
步骤一:导入蓝图类

from flask import Blueprint
#  在views目录下的相应的视图py文件中

步骤二:实例化得到蓝图对象

us=Blueprint('user',__name__)
#  在views目录下的相应的视图py文件中

步骤三:在app中注册蓝图

app.register_blueprint(us)
# 在src/__init__.py中

步骤四:在不同的views.py(order.py,user.py)中使用蓝图注册路由,此后就不用app注册路由而是用蓝图对象注册路由

@us.route('/login')
# 在视图函数上

2.目录结构:
根目录
src
static
banner.jpg
templates
user.html
views
orders.py
user.py
init.py
models.py
manage.py
image
3.代码
src/views/orders.py:

from flask import Blueprint
'''生成蓝图对象'''
order_bp = Blueprint('order', __name__)

@order_bp.route('/order')
def order():
    return 'order页面'

@order_bp.route('/order/list')
def list():
    return 'order列表'

src/views/user.py:

from flask import Blueprint, render_template

user_bp = Blueprint('user', __name__)

@user_bp.route('/user')
def user_detail():
    return render_template('user.html',name='max')

src/init.py:

from flask import Flask

app = Flask(__name__)

app.debug = True
app.secret_key = 'yf7rewt6y374g'

'''manage.py中的这行代码执行:from src import app,src/__init__下的所有代码都会执行'''
from .views.user import user_bp
'''执行这两句,views下两个py文件就会执行'''
from .views.orders import order_bp
app.register_blueprint(user_bp)
app.register_blueprint(order_bp)

src/models.py:

#  这里以后写表模型

manage.py:

from src import app

if __name__ == '__main__':
    app.run()

1.3 蓝图的请求扩展

蓝图也有自己的请求扩展,并且在哪个视图函数中生成的蓝图对象,只对该文件中的视图函数生效。而是用app注册的请求扩展则是对所有视图函数生效
src/views/order.py:

from flask import Blueprint

order_bp = Blueprint('order', __name__)
'''用蓝图对象点请求扩展装饰器,只要访问了/orde或者/order/list都会会走请求扩展,而执行user.py中的视图函数则不会执行该请求扩展'''
@order_bp.before_request
def brfore():
    print('请求来了')

@order_bp.after_request
def after(response):
    print('请求走了')
    return response

@order_bp.route('/order')
def order():
    return 'order页面'

@order_bp.route('/order/list')
def list():
    return 'order列表'

image

1.4 大型项目使用蓝图

1.目录结构
根目录
src
admin # 可以看成一个app
static
banner2.png
templates
admin_home.html
init.py
models.py
views.py
home # 可以看成一个app
static
templates
init.py
models.py
views.py
order # 可以看成一个app
static
templates
init.py
models.py
views.py
init.py
settings.py
manage.py
image
2.代码
src/admin/init.py:

from flask import Blueprint

admin_bp = Blueprint('admin',__name__,static_folder='static',template_folder='templates')
from . import views

src/admin/models.py:

#  这里写模型表

src/admin/views.py:

from flask import render_template
from . import admin_bp

@admin_bp.route('/home')
def home():
    return render_template('admin_home.html')

src/home/init.py:

from flask import Blueprint

home_bp = Blueprint('home',__name__,static_folder='static',template_folder='templates')
from . import views

src/home中其他地方无代码,后期根据业务需求按照app扩写
src/order/init.py:

from flask import Blueprint

order_bp = Blueprint('order', __name__, static_folder='static', template_folder='templates')
from . import views

src/order/views.py:

from . import order_bp
#  请求扩展
@order_bp.before_request
def before():
    print('order的请求来了')

@order_bp.route('/order')
def index():
    return 'order页面'

src/init.py:

from flask import Flask

app = Flask(__name__)

app.config.from_pyfile('settings.py')

#  注册蓝图
from .admin import admin_bp
from .home import home_bp
from .order import order_bp
#  在访问路由的时候需要根据蓝图中注册的路由再拼接视图函数中的路由,注册蓝图时的路由前缀必须以/开头
app.register_blueprint(admin_bp,url_prefix='/admin')
app.register_blueprint(home_bp,url_prefix='/home')
app.register_blueprint(order_bp,url_prefix='/order')

src/settings.py:

#  象征性的写了一个配置文件,也可以用类的方法来配置
DEBUG = True

manage.py:

from src import app

if __name__ == '__main__':
    app.run()

image
image
image

2.g对象

1.g对象的作用:在整个请求(不是整个项目)的全局,可以放值,也可以取值。在任意位置导入即可。之所以没有用request作为全局对象是因为request的属性太多,使用频率太高,怕数据污染。
在其他框架中叫context(上下文)
2.g对象的使用:
放值:g.变量名=值
取值:g.变量名

from flask import Flask,request,g

app = Flask(__name__)
app.debug = True

@app.route('/')
def index():
    name = request.args.get('name')
    g.name = name
    return g.name

if __name__ == '__main__':
    app.run()

g对象虽然是全局的,但是对于每个请求存入的值不会乱:
image
image
的但是当我们想要将name存入对象,再从另一个请求当中拿出来,发现会直接报错:
image
报上述错误的原因是g对象的存入值和取值只能再一次请求中。这也是g对象和session的区别:
g是只针对的当次请求
session针对于多次请求

但是针对于一个请求的视图函数调用了另一个视图函数,两个特视图函数之间依旧可以共享g对象中的值:

from flask import Flask,request,g

app = Flask(__name__)
app.debug = True

def add(a,b):
    print('g对象',g.name)
    return 'g对象取值'

@app.route('/')
def index():
    name = request.args.get('name')
    g.name = name
    add(1,2)
    return 'g对象存入值'

if __name__ == '__main__':
    app.run()

image
image
同理,同一个请求也可以在请求扩展中的before_request中存入值,在视图函数中取值:

from flask import Flask,request,g

app = Flask(__name__)
app.debug = True

@app.before_request
def before():
    g.name='111'

@app.route('/')
def index():
    name = request.args.get('name')
    print(g.name)
    return '222'

if __name__ == '__main__':
    app.run()

image