flask之蓝图和前后端变量传递
一、蓝图 Blueprint
在Flask中,蓝图(Blueprint)是一种结构化应用程序的方法,特别适用于大型项目。蓝图允许您将应用程序拆分成更小、更可管理的部分,使代码更具模块性和可重用性。
1、蓝图的优势
模块化: 通过蓝图,可以将应用程序的不同部分(比如用户管理、博客模块等)分开,简化管理。
可重用性: 可以在多个应用中使用相同的蓝图模块。
清晰的代码结构: 便于团队协作,因为每个模块相对独立。
2、蓝图的使用步骤
创建蓝图:在py软件包或者py文件中定义,这里以软件包为例子
1 2 3 4 5 | tree image_manager image_manager ├── __init__.py ├── image_service.py └── views.py |
views 是视图函数,定义了路由,__init__.py 文件中执行导入,引用方便
1 2 3 4 5 | from flask import Blueprint image_bp = Blueprint( 'image' , __name__) from .views import * |
补充: image_bp = Blueprint('image', __name__)
这里‘image’ 是蓝图的名字,和路由没有关系
注册蓝图: app.register_blueprint(bpname_bp, url_prefix=config.APP_URL_PREFIX)
应用程序中注册这个蓝图,通常是在app.py
或类似的主应用程序文件中。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | from flask import Flask, render_template, redirect, url_for from flask_cors import CORS app = Flask(__name__, template_folder = 'template' , static_folder = "static" , static_url_path = config.APP_URL_PREFIX) CORS(app, supports_credentials = True ) app.config[ 'SESSION_COOKIE_NAME' ] = '/serviceops' app.config[ 'SECRET_KEY' ] = 'hello-healsci-service-ops' # 注册蓝图 app.register_blueprint(image_bp, url_prefix = config.APP_URL_PREFIX) @app .errorhandler( 500 ) def ERROR_500(e): return render_template( '500.html' , message = e.description) @app .errorhandler( 404 ) def ERROR_404(e): return render_template( '404.html' ) @app .route( '/' ) @login_required def root_path(): return redirect(url_for( 'swarm.service_list' )) if __name__ = = '__main__' : app.run(host = '0.0.0.0' , port = 5000 ) |
注册时,可以指定url_prefix
来为蓝图中的所有路由加上一个公共的URL前缀。
定义路由: 使用装饰器 @bpname_bp.route('/xxx')
1 2 3 4 5 6 7 | @image_bp .route( '/images' ) @login_required def image_list(): image_list = get_image_list(config.master_ip) image_file_list = get_files_from_server_path() mount_path = get_image_upload_mount_path() return render_template( 'images.html' , image_list = image_list, image_file_list = image_file_list, mount_path = mount_path) |
由于蓝图在注册时被指定了url_prefix
,真正的访问路径是<url_prefix>/images
,
路由实现的过程
- 蓝图名称(
swarm
): 仅用于内部标识,和某些工具或调试日志有关,但不影响URL。 url_prefix
: 用于定义蓝图内所有路由的公共前缀。- 具体路由: 在蓝图内通过
@swarm_bp.route(xxx)
定义的路径。 - 最终路径: 由
url_prefix
和具体路由结合,形成完整的路径,即http://ip/xxx/xxx
。
3、项目结构建议
对于大型项目,建议将蓝图放在模块或包内,比如:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 | tree service - ops service - ops ├── Dockerfile ├── Jenkinsfile ├── README.md ├── app.py ├── app_util.py ├── build_info.txt ├── config.py ├── db │ └── db_operation.py ├── docker - entrypoint.sh ├── gunicorn.conf.py ├── healthcheck.csv ├── image_manager │ ├── __init__.py │ ├── image_service.py │ └── views.py ├── monitor_expr.csv ├── pip.conf ├── release_version.txt ├── requirements.txt ├── schedule │ ├── __init__.py │ └── task.py ├── scripts │ └── check.sh ├── sources. list ├── static │ ├── css │ │ ├── bootstrap3. 3.0 . min .css │ │ └── jquery - ui - 1.10 . 4.css │ └── js │ ├── bootstrap3. 3.0 . min .js │ ├── echarts.js │ ├── healsci_alarm.js │ ├── jquery - ui - 1.10 . 4.js │ ├── jquery3. 5.1 . min .js │ └── jsencrypt.js ├── template │ ├── 404.html │ ├── 500.html │ ├── add_service.html │ ├── container_log.html ├── tests │ ├── data │ │ └── docker_api_service.json │ ├── test_monitor_jmeter.py │ ├── test_monitor_service.py │ ├── test_std_dataset_service.py │ └── test_swarm_service.py └── user_manager ├── __init__.py ├── user_service.py └── views.py |
二、前端引用后端的变量
在Flask项目中,将变量传输到前端HTML页面的常用方式是通过render_template
函数。该函数用于渲染模板,并允许你将Python变量传递给模板以供使用。在Flask中,有几种方法可以将数据传输到前端HTML页面:
1、render_template
这是Flask中最直观和常用的方法。你可以在调用render_template
时,将变量作为关键字参数传递给模板,在Jinja2模板中直接使用这些变量。
1 2 3 4 5 6 7 | from flask import render_template def image_list(): image_list = get_image_list(config.master_ip) image_file_list = get_files_from_server_path() mount_path = get_image_upload_mount_path() return render_template( 'images.html' , image_list = image_list, image_file_list = image_file_list, mount_path = mount_path) |
在images.html
中,你可以通过Jinja2语法来访问这些变量:
1 2 3 4 5 6 7 | <ul> { % for image in image_list % } <li>{{ image }}< / li> { % endfor % } < / ul> <p>Mount Path: {{ mount_path }}< / p> |
2、flask.jsonify
如果你需要在前端以JavaScript方式处理数据,尤其是通过AJAX请求时,可以使用flask.jsonify
来返回JSON格式数据。
1 2 3 4 5 6 | from flask import jsonify @app .route( '/api/images' ) def api_image_list(): image_list = get_image_list(config.master_ip) return jsonify(image_list = image_list) |
然后在JavaScript中通过AJAX请求处理:
1 2 3 4 5 | fetch( '/api/images' ) .then(response = > response.json()) .then(data = > { console.log(data.image_list); }); |
3、 session
和 g
对象
在Flask中,session
对象可以用于在用户会话中存储变量,而g
对象用于在请求上下文中存储数据。这些数据可以在渲染模板时访问。
g对象是global的缩写,python 中global是一个关键字所以缩写成g表示。
g只针对于当前请求,session针对于这个用户的所有请求
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | from flask import Flask, render_template, g, session app = Flask(__name__) app.secret_key = 'jingzhiz' @app .before_request def before_request(): g.user = 'jingzhiz' session[ 'info' ] = { '爱好' : '洗脚' , '年龄' : 18 , '性别' : '男' } @app .route( '/' ) def index(): # put application's code here # raise Exception('测试异常') return '这里是根路径返回的结果' @app .route( '/home' ) def home(): return render_template( 'home.html' ) if __name__ = = '__main__' : app.run() |
在html模版中访问
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | <!DOCTYPE html> <html lang = "en" > <head> <meta charset = "UTF-8" > <title>Title< / title> <p>使用标签:{{ add( 5 , 6 ) }}< / p> <p>使用过滤器:{{ "Hello, World!" | reverse }} < / p> <p>User: {{ g.user }}< / p> <p>Session Data: {{ session[ 'info' ][ '爱好' ], session[ 'info' ][ '年龄' ] }}< / p> < / head> <body> < / body> < / html> |
4、全局上下文处理器 @app.context_processor
@app.template_global() 也有类似的作用
全局上下文处理器可以用于在每个模板中自动提供一些变量。
1 2 3 | @app .context_processor def inject_user(): return dict (user = get_current_user()) |
这使得每个模板自动具备user
变量:
1 | <p>User: {{ user }}< / p> |
这些方法可以根据你的具体需求和使用场景进行适当选择。
render_template
是最直接的选择,特别适用于基本的服务器端渲染,而jsonify
更适合用于AJAX请求和动态页面的数据交互。
使用session
或g
对象可以在请求间或用户会话中共享数据,而全局上下文处理器方便应用程序全局的变量注入。