Flask 应用最佳实践
一个好的应用目录结构可以方便代码的管理和维护,一个好的应用管理维护方式也可以强化程序的可扩展性
应用目录结构
假定我们的应用主目录是”flask-demo”,首先我们建议每个应用都放在一个独立的包下,假设包名是”myapp”。所以,整个应用的目录结构如下:
flask-demo/├ run.py # 应用启动程序├ config.py # 环境配置├ requirements.txt # 列出应用程序依赖的所有Python包├ tests/ # 测试代码包│ ├ __init__.py │ └ test_*.py # 测试用例└ myapp/├ admin/ # 蓝图目录├ static/│ ├ css/ # css文件目录│ ├ img/ # 图片文件目录│ └ js/ # js文件目录├ templates/ # 模板文件目录├ __init__.py ├ forms.py # 存放所有表单,如果多,将其变为一个包├ models.py # 存放所有数据模型,如果多,将其变为一个包└ views.py # 存放所有视图函数,如果多,将其变为一个包
应用的创建代码放在”myapp/__init__.py”中:
from flask import Flask from myapp.admin import admin import configapp = Flask(__name__) app.config.from_object('config') app.register_blueprint(admin)from myapp import views
我们把创建应用的代码与应用的启动剥离开,并且在应用对象创建之后,再导入视图模块,因为此时视图函数上的”@app.route()”才有效。视图模块包括了所有的视图函数及路由,如果有多个视图模块,则一并导入。在主目录下的”run.py”内,我们才放入应用的启动代码:
from myapp import appapp.run(host='0.0.0.0')
此后,应用的启动都是通过执行”run.py”来完成。蓝图里的目录结构跟应用基本上一样,也是”static”目录放所有静态文件,”templates”目录放所有模板文件,”views.py”存放所有视图,”forms.py”存放所有表单,”models.py”存放所有数据模型,我就不画了。蓝图对象的初始化也放在”__init__.py”里,并在初始化后导入蓝图中的视图模块,这样风格可以跟应用保持一致:
from flask import Blueprintadmin = Blueprint('admin', __name__, url_prefix='/admin')from myapp.admin import views
还有一种风格,就是将蓝图的模板和静态文件也放在myapp的”templates”和”static”目录下,只是在这些目录下创建与蓝图同名的子目录,比如:
flask-demo/...└ myapp/├ admin/ # 蓝图目录├ static/│ ├ admin/ # 蓝图admin专有的js, css, 图片文件│ ├ css/ # css文件目录│ ├ img/ # 图片文件目录│ └ js/ # js文件目录├ templates/ # 模板文件目录│ └ admin/ # 蓝图admin的模板文件├ __init__.py ...
这样做的好处就是便于资源统一管理。此时蓝图中获取模板文件或静态文件,都需要加个前缀,比如”render_template(‘admin/hello.html’)”。个人觉得,如果你的蓝图只是为了划分模块,蓝图之间重用部分较多,可以用这个方法。如果蓝图之间比较独立,比如用户站点和管理员后台,就建议采用第一种方法。
应用工厂 App Factory
Flask官方建议采用工厂的模式来创建应用。什么是应用工厂呢?让我们对上例中”myapp”下的”__init__.py”文件作如下修改:
from flask import Flask from flask_mail import Mail from flask_sqlalchemy import SQLAlchemy from werkzeug.utils import import_stringmail = Mail() db = SQLAlchemy()blueprints = ['myapp.main:main','myapp.admin:admin', ]def create_app(config):app = Flask(__name__)app.config.from_object(config)# Load extensions mail.init_app(app)db.init_app(app)# Load blueprintsfor bp_name in blueprints:bp = import_string(bp_name)app.register_blueprint(bp)return app
我们不在代码中直接创建应用,而是通过调用”create_app()”方法来返回一个应用对象,这个”create_app()”就是应用工厂方法。在工厂方法里,我们分别加载了配置,扩展和蓝图。这里要注意,因为没有一个全局的app对象,所以上一节例子中的应用视图就无法工作,因为无法执行”@app.route()”。怎么办?还好Flask有个蓝图功能,我们将主程序里的视图,数据模型,表单等也放到一个蓝图下,这里起名为”main”。创建蓝图时不指定”url_prefix”,这样它的URL前缀就是根路径。
from flask import Blueprintmain = Blueprint('main', __name__)from myapp.main import views
然后在视图函数里用蓝图对象路由即可,这个对象在蓝图创建后就可见了:
from myapp.main import main@main.route('/') def index():return '<h1>Hello World from app factory!</h1>'
有了应用工厂后,我们怎么启动应用呢。这个就简单了,我们修改下主目录下的”run.py”文件:
from myapp import create_app import configapp = create_app('config')app.run(host='0.0.0.0', debug=True)
这样应用就可以被启动了
应用工厂好处如下:
- 在跑自动测试时,每个测试用例都通过应用工厂来获取各自的应用,这样测试用例之前不会互相污染
- 方便获取同一应用的多个实例,比如debug版和release版,并根据需要启用,甚至于同时启用来服务不同的目的
多应用组合
上节最后说到了多个应用(在同一Python进程中)同时启用。这个怎么做到?我们先来深入下Flask中的”app.run()”方法。这个方法本质上是调用了Werkzeug中的”werkzeug.serving.run_simple()”方法来启动一个WSGI服务器,前面例子中”app.run(host=’0.0.0.0′, debug=True)”等同于调用:
from werkzeug.serving import run_simple# debug=True means use_reloader=True and use_debugger=True run_simple('0.0.0.0', 5000, app, use_reloader=True, use_debugger=True)
我们曾经说过Flask就是基于Werkzeug和Jinja2建立起来的,Werkzeug帮助Flask封装了很多WSGI层面的操作。所以,要同时启用多个应用,就要利用Werkzeug的方法,大家看下面的例子:
from werkzeug.wsgi import DispatcherMiddleware from werkzeug.serving import run_simple from myapp import create_app import configrelease_app = create_app('config.release') debug_app = create_app('config.debug')app = DispatcherMiddleware(release_app, {'/test': debug_app})run_simple('0.0.0.0', 5000, app, use_reloader=True, use_debugger=True)
我们将这段代码保存在主目录下的”run_batch.py”中,执行它后你会发现。release应用挂在了服务器的根路径上,而debug应用挂在了服务器的”/test”路径上了。这样,我们就实现了两个应用同时启用。”werkzeug.wsgi.DispatcherMiddleware”是一个调度中间件,它的实例化参数就是一组应用及其挂载路径的键值对,没提供挂载路径就意味着挂到根目录上。
此外,”run_simple()”方法只能用于开发环境,生产环境还是建议大家部署在一个强大的Web服务器上
转载于:https://www.cnblogs.com/Erick-L/p/7025649.html
Flask 应用最佳实践相关推荐
- docker-compose 运行 Flask 应用最佳实践
背景 以前部署应用,需要各种环境配置,各种shell操作才能搭建一套可用的服务.现在有了Docker之后,部署方式变了更加容易,不容易出现配置错误,环境不一致问题.解决了在本地环境可以运行,迁移到 ...
- Django 开发中的最佳实践之一
为什么80%的码农都做不了架构师?>>> Django 开发中的最佳实践之一 本文关注 Django 开发中调试的部分. 出自 Flask 项目旗下的 Werkzeug deb ...
- python组件的react实现_React-Router动态路由设计最佳实践
写在前面 随着单页应用(SPA)概念的日趋火热,React框架在设计和实践中同样也围绕着SPA的概念来打造自己的技术栈体系,其中路由模块便是非常重要的一个组成部分.它承载着应用功能分区,复杂模块组织, ...
- django 最佳实践_通过这些最佳实践来改进Django项目
django 最佳实践 by Ofir Chakon 由Ofir Chakon 通过这些最佳实践来改进Django项目 (Improve your Django project with these ...
- Docker最佳实践:构建最小镜像
镜像大小其实是衡量我们容器打包技术的重要指标,我们应该在不影响应用正常运行的情况下,尽量让我们的容器镜像变得更小,这样,不管是从安全还是维护效率角度来讲,都是最佳实践. 本文我们从两种情况阐述我们的问 ...
- 编写高性能Java代码的最佳实践
编写高性能Java代码的最佳实践 摘要:本文首先介绍了负载测试.基于APM工具的应用程序和服务器监控,随后介绍了编写高性能Java代码的一些最佳实践.最后研究了JVM特定的调优技巧.数据库端的优化和架 ...
- 提示和技巧:光线跟踪最佳实践
提示和技巧:光线跟踪最佳实践 Tips and Tricks: Ray Tracing Best Practices 本文介绍了在游戏和其他实时图形应用程序中实现光线跟踪的最佳实践.我们尽可能简短地介 ...
- SQL Server 最佳实践分析器使用小结
Best Practices Analyzer Tool for Microsoft SQL Server 2000是Microsoft SQL Server开发团队开发的一个数据库管理工具,可以让你 ...
- 使用ADO.NET 的最佳实践(zz)
数据访问:使用 ADO.NET 的最佳实践(ADO.NET 技术文档) 发布日期: 4/1/2004 | 更新日期: 4/1/2004 摘要:编写 Microsoft ADO.NET 代码的最佳实践, ...
最新文章
- 客户机不能看到分配的dhcp_交换机配置DHCP后下挂用户获取不到IP地址或者获取缓慢...
- 连接池你用对了吗?一次Unexpected end of stream异常的排查
- 07-阻塞赋值与非阻塞赋值原理分析——小梅哥FPGA设计思想与验证方法视频教程配套文档...
- 算法 - pyhton - 二分查找
- Setting up Jupyter with Python 3 on Ubuntu
- 三十三、深入Vue.js语法(上篇)
- 详解车道线检测数据集和模型 VIL-100: A New Dataset and A Baseline Model for Video Instance Lane Detection
- Scollector+Bosun+OpenTSDB的监控方案逻辑组网
- 直播电商都用上 AI 实时翻译了!歪果仁也能听懂李佳琦
- mysql 多表连接技巧_【Mysql进阶技巧(1)】 MySQL的多表关联与自连接
- win10 更新计算机时间,win10下如何更改系统更新时间和更新方式?win10设置系统更新时间和更新方式的技巧...
- 飞思卡尔单片机高效c语言编程,飞思卡尔单片机高效c语言编程(中文)新.pdf
- AGV小车导航控制 研一《智能控制》课程文献阅读作业
- 初识C语言——C语言基础知识
- 百度没有柳传志,联想没有李彦宏
- Python学习(一) 准备工作
- OPPO R8107刷机包下载_OPPO R8107密码忘记了?点击进来搞定
- 带着问题学 Kubernetes 抽象对象 Service 服务间调用
- 最受欢迎的11个Python编程软件,让你的工作效率直接原地起飞
- c语言编译器能不能找出逻辑错误,《C Primer Plus》- 第二章 C语言概述
热门文章
- java jbutton 不显示_java让JButton按钮变成不可见
- asp.net mvc redis同步mysql_Mysql和Redis数据同步策略 - 元思 - 博客园
- 线性表部分知识点小结
- java 连接oracle_「事件驱动架构」使用GoldenGate创建从Oracle到Kafka的CDC事件流
- Codeforces Round #518 (Div. 2): F. Knights(神题)
- Wannafly挑战赛9: D. 造一造(组合数)
- bzoj 3407: [Usaco2009 Oct]Bessie's Weight Problem 贝茜的体重问题(DP)
- HDU 5979 2016ICPC大连 I: Convex
- matlab meshgrid
- C++ STL 容器的合并、求差集、交集等操作实例 含详细注释版