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对象用于在请求上下文中存储数据。这些数据可以在渲染模板时访问。

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请求和动态页面的数据交互。

使用sessiong对象可以在请求间或用户会话中共享数据,而全局上下文处理器方便应用程序全局的变量注入。

 

posted @ 2024-09-19 13:51  凡人半睁眼  阅读(18)  评论(0编辑  收藏  举报