正规网站设计制作公司,专业定制网站,快速开发平台 免费开源,网站建设jiage前面我们了解了 Flask 框架的特性和一些用法#xff0c;比如创建一个简单应用、做些页面#xff0c;以及增加鉴权模块等#xff0c;如果要将 Flask 用于实际项目开发#xff0c;还需要了解一下 Flask 项目结构。
Flask 是一个轻量级的 Web 框架#xff0c;扩展性强#…前面我们了解了 Flask 框架的特性和一些用法比如创建一个简单应用、做些页面以及增加鉴权模块等如果要将 Flask 用于实际项目开发还需要了解一下 Flask 项目结构。
Flask 是一个轻量级的 Web 框架扩展性强灵活性高容易上手不过 Flask 没有给出明确的项目结构而是让开发者根据实际需求创建适合自己的项目结构。对于初学者来说面临的困难可能是不知道如何组织代码特别是在看一些别人的代码时弄不清结构对理解和学习造成一定障碍。
需要说明的是今天所介绍的结构并不是最好的不同的项目不同的团队不同的理念会有不同的结构今天介绍的只是一个参考。
我们就那之前的 Flask数据持久化 章节的练习作为实践。
按功能组织
按功能指的是将 Web 项目的不同职能划分开比如路由部分、模型部分、业务逻辑部分等
目录结构
project/ forms/ myform.py ... models/ __init__.py profile.py user.py ... routes/ __init__.py home.py profile.py ... static/ ... services/ __init__.py ... templates/ createprofile.html profile.html ... __init__.py config.py
可以看到项目根目录下分为: forms表单存放表单对象 models模型存放数据模型即库表在程序中的映射对象以及对象之间的关系 routes路由存放请求路由以及处理逻辑 static静态文件Flask 约定存放静态文件的目录 templates模板Flask 约定存放页面模板的目录 services服务存放业务逻辑或者其他服务类功能 __init__.pyFlask app 初始化方法 config.py项目配置文件
这样的分类相当于将之前写到一个代码文件app.py中的逻辑按功能划分开当项目逐渐变大变复杂后这样的划分有助于开发和维护
初始化
按功能划分开比较容易理解不过将分开的部分有机结合起来是个问题 推荐的方式是在每个目录下创建一个 __init__.py 文件有两个作用: 将目录变为包package方便其他地方引入 做些初始化工作例如将目录下的内容统一起来提供一站式装载
初始化模型
数据模型放在 models 目录下一般数据模块需要和数据库交互另外每个模型需要有个数据库实例来创建模型以及字段定义
首先创建目录的 __init__.py 代码文件
from flask_sqlalchemy import SQLAlchemydb SQLAlchemy()def init_app(app): db.init_app(app) return db 使用之前了解过的 Sqlalchemy 库做数据映射ORM框架 定义一个数据库对象 db注意构造方法没有传递 app 参数是因为此时还得到 app 定义一个 init_app 函数接收一个参数 app就是 Flask app用 db.init_app 方法初始化 Flask app
模型代码示例 project/models/profile.py
from . import dbclass Profile(db.Model): id db.Column(db.Integer, primary_keyTrue) name db.Column(db.String(20)) birthday db.Column(db.Date()) createtime db.Column(db.DateTime()) about db.Column(db.Text()) 因为是在 models 目录下的代码文件所以通过当前目录引入在 __init__.py 中定义的 db用来定义数据模型及其字段 字段在前面的数据持久化中有详细说明这里省略解释
初始化路由
当路由处理代码被分开之后在主程序代码中初始化会变得比较麻烦幸好 Flask 有个 blueprint蓝图的概念能很好的将分离出来的代码管理起来确切的说 blueprint 的作用不止于此这里只是需要用到它的部分功能 Web 项目被分成多个部分之后每个部分可以单独成为一个子应用blueprint 的作用就是可以让子应用的编写方式用在主应用中一样比如注册路由处理请求等使用前先创建一个 blueprint 实例然后再将实例注册到 Flask app 实例中就好了。 路由处理定义示例project/routes/home.py:
from flask import Blueprinthome_bp Blueprint(home_bp, __name__)home_bp.route(/, methods[GET, POST])def index(): return Hello World!, 200 引入 Flask 的 blueprint 模块 初始化 blueprint 实例的实例 home_bp第一个参数是 终端点endpoint 的名称用在 url_for 方法中第二个参数是作为模块被引入时候的名称 使用和 blueprint 实例同名的装饰器定义路由代替了之前 app.route 的方式相当于 blueprint 实例是一个 Flask app 实例 视图函数的定义之前 Flask app 实例中的没有区别这里只是简单的返回文字和状态
再看看路由模块的初始化routes/__init__.py:
from .home import home_bpfrom .profile import profile_bpdef init_app(app): app.register_blueprint(home_bp) app.register_blueprint(profile_bp) 从当前目录下引入具体路由文件从中引入 blueprint 实例 定义初始化方法参数就是 Flask app 实例用 register_blueprint 方法将 blueprint 注册到 Flask app 实例中
Flask app 工厂方法
在之前的介绍中在 app.py 中编写所有的东西并且通过 app.run() 来启动应用在实际项目中推荐用 app 工厂方法的方式来启动好处是 便于测试可以在不同的测试用例中创建特别的 app 实体 多实例运行如果需要一个应用的多个版本可以在一个应用进程中运行多个实例而不必部署多个 Web 服务器将在 Flask 部署中介绍
创建 Flask app 写在 project/__init__.py 中
from flask import Flaskfrom .config import configfrom . import models, routesdef create_app(config_namedefault): app Flask(__name__) app.config.from_object(config[config_name]) config[config_name].init_app(app) models.init_app(app) routes.init_app(app) return app 引入 flask 库 从当前目录下引入配置文件 引入上面定义的模型模块和路由模块 定义工厂方法默认方法名是 create_app如果其他名称需要在启动应用时指定随后介绍工厂方法有个参数用来指定需要加载的配置内容且设定了默认值随后介绍 工厂方法中先创建 Flask app 实例然后加载配置最后为模块初始化 模型和路由 最后返回 Flask app 实例方便测试和应用启动时的调用
工厂方法比单个文件写法更清爽修改起来也更简单另外这样定义还可以避免循环依赖问题 循环依赖如果在工厂方法中直接定义数据库模块 db在模型中需要引用 db而工厂方法又需要用模型来初始化 Flask app就会引起循环依赖问题 启动项目
通过工厂方法创建的应用因为没有明确的 app.run() 调用不能直接像在前一样直接运行文件而是要用 flask 命令行方式来启动
正常启动
启动之前需要先设置 FLASK_APP 环境变量指定需要运行的 Flask 项目 值为项目文件夹名即项目名: Linux 或者 Mac
export FLASK_APPproject Windows 命令行
set FLASK_APPproject Powershell
$env:FLASK_APPproject
然后在项目目录的上一层目录下执行命令启动项目:
flask run
如果一切正常就可以看到类似的结果: * Serving Flask app project * Environment: production WARNING: Do not use the development server in a production environment. Use a production WSGI server instead. * Debug mode: off * Running on http://127.0.0.1:5000/ (Press CTRLC to quit)
设置启动参数
前面工厂方法可以定义一些参数如何来指定呢其中一种方法是设置环境变量 FLASK_APP例如将 congfig_name 参数设置为 testing Linux 或者 Mac
export FLASK_APPproject:create_app(testing) Windows 命令行
set FLASK_APPproject:create_app(testing) powershell
$env:FLASK_APPproject:create_app(testing) project 是 Flask app 所在的模块名与上面直接写 project 一样 冒号(:)后即为工厂方法的名并且将参数带入
您可能已经想到这种方式可以解决工厂方法名不是默认 create_app 的情况了例如工厂方法名为 myapp_factory,以 Linux 环境为例:
export FLASK_APPproject:myapp_factory()
按业务组织
一个大型项目中会包含很多子业务比如人员管理、订单管理、统计报表等等每一部分都可以是独立的项目在 Flask 中按照业务的方式将文件划分开就是按业务方式来组织项目结构这样的组织方式有助于并行开发和分而治之。
大体的结构是
project/ __init__.py config.py db.py auth/ __init__.py route.py models.py templates/ blog/ __init__.py route.py models.py templates/ ... 项目结构中__init__.py 和 config.py 是整个应用的 auth、blog 目录是子业务可以看到每个内部有自己的路由、模型和模板文件夹 db.py 是数据库连接模块为各个子业务提供统一的数据库连接和模型支持因为是单独的数据库模块所以不会出现前面说的循环依赖问题需要使用数据库模块的地方直接导入就行。
按业务组织方式中每个子业务都是以 blueprint 的方式注册到 Flask app 上的在按功能组织的方式中我们只将路由用 blueprint 注册了其实可以将 blueprint 看成一个独立的 Flask app不过不用真的去部署只需要注册到真正的 Flask app 上就行。
项目配置
之前的练习中都是将配置写到 app.py 中的只是为了方便练习。实际项目中配置是很重要的部分系统研发过程中需要经历不同的环境比如开发环境测试环境和生产环境如果配置错了开发环境连接上了生产环境的数据库那可就糟糕了相反开发环境为了方便查错往往开启了 Debug 模式如果放在生产环境中将会带来很大的性能损耗。
Python 中提供了丰富的配置处理方式今天就 Flask 的配置利用实例简单介绍下不过介绍的不见得就是最好的只是一种解决思路大家可以根据具体项目有所调整。
看一下代码
import osbasedir os.path.abspath(os.path.dirname(__file__))class Config: SECRET_KEY os.environ.get(SECRET_KEY) or hard to guess string SQLALCHEMY_COMMIT_ON_TEARDOWN True staticmethod def init_app(app): passclass DevelopmentConfig(Config): DEBUG True SQLALCHEMY_DATABASE_URI os.environ.get(DEV_DATABASE_URL) or sqlite:/// os.path.join(basedir, data-dev.db)class TestingConfig(Config): TESTING True SQLALCHEMY_DATABASE_URI os.environ.get(TEST_DATABASE_URL) or sqlite:/// os.path.join(basedir, data-test.db)class ProductionConfig(Config): SQLALCHEMY_DATABASE_URI os.environ.get(DATABASE_URL) or sqlite:/// os.path.join(basedir, data.db)config { development: DevelopmentConfig, testing: TestingConfig, production: ProductionConfig, default: DevelopmentConfig} 实例项目中使用的数据库是 Sqlite需要指定数据库文件目录所以在定义了统一的目录 basedir获取的是项目所在文件夹目录因为 config.py 就在项目根目录中 定义了 Config 基类用类属性设置了 Flask app 的一些配置其中 init_app 是为了在初始化 app 是附加一些额外配置用的 定义了三个不同场景下的配置子类分别是开发环境、测试环境和生产环境大同小异特别需要注意的是数据库文件名称不同的场景有不同的名称 将不同的配置放在一个词典dict中在 Flask app 工厂方法中通过参数来选择具体的配置类为了严谨还设置的默认配置显然默认为开发环境是很好的选择
有必要说明的是Flask app 有多种设置配置的方式常用的如: 属性指定如 app.config[MYCONFIG] xxxx 对象获取如 app.config.from_object(configObj) 配置文件app.config.from_pyfile(pyfilepath) JSONapp.config.from_json(jsonfilename)
总结
今天介绍了一个简单的 Flask 项目化结构并利用之前做过的数据持久化的练习做了项目化后的代码说明并且说明了按功能和按业务两种项目组织方式最后介绍了 Flask 项目中配置的方式。总之 Flask 是一个宽松的简单的 Web 框架每个人都可打造自己的一套项目构建方式不过对于刚开始接触的同学或者为了交流方便还是有必要了解一下一般的组织方式希望对您有所启发。
最后示例代码中提供了较为完整的例子其中还有如何自定义数据库初始化命令的例子请您参考。