flask之蓝图和前后端变量传递
一、蓝图 Blueprint
在Flask中,蓝图(Blueprint)是一种结构化应用程序的方法,特别适用于大型项目。蓝图允许您将应用程序拆分成更小、更可管理的部分,使代码更具模块性和可重用性。
1、蓝图的优势
模块化: 通过蓝图,可以将应用程序的不同部分(比如用户管理、博客模块等)分开,简化管理。
可重用性: 可以在多个应用中使用相同的蓝图模块。
清晰的代码结构: 便于团队协作,因为每个模块相对独立。
2、蓝图的使用步骤
创建蓝图:在py软件包或者py文件中定义,这里以软件包为例子
tree image_manager image_manager ├── __init__.py ├── image_service.py └── views.py
views 是视图函数,定义了路由,__init__.py 文件中执行导入,引用方便
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或类似的主应用程序文件中。
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')
@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、项目结构建议
对于大型项目,建议将蓝图放在模块或包内,比如:
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模板中直接使用这些变量。
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语法来访问这些变量:
<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格式数据。
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请求处理:
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针对于这个用户的所有请求
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模版中访问
<!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() 也有类似的作用
全局上下文处理器可以用于在每个模板中自动提供一些变量。
@app.context_processor
def inject_user():
return dict(user=get_current_user())
这使得每个模板自动具备user变量:
<p>User: {{ user }}</p>
这些方法可以根据你的具体需求和使用场景进行适当选择。
render_template是最直接的选择,特别适用于基本的服务器端渲染,而jsonify更适合用于AJAX请求和动态页面的数据交互。
使用session或g对象可以在请求间或用户会话中共享数据,而全局上下文处理器方便应用程序全局的变量注入。

浙公网安备 33010602011771号