当前位置: 首页 > news >正文

Flask 项目结构

前面我们了解了 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__.py:Flask app 初始化方法

  • config.py:项目配置文件

这样的分类,相当于将之前写到一个代码文件(app.py)中的逻辑,按功能划分开,当项目逐渐变大变复杂后,这样的划分有助于开发和维护

初始化

按功能划分开,比较容易理解,不过将分开的部分有机结合起来是个问题, 推荐的方式是,在每个目录下创建一个 __init__.py 文件,有两个作用:

  1. 将目录变为包(package),方便其他地方引入

  2. 做些初始化工作,例如将目录下的内容统一起来,提供一站式装载

初始化模型

数据模型放在 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_key=True)    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 工厂方法的方式来启动,好处是:

  1. 便于测试,可以在不同的测试用例中创建特别的 app 实体

  2. 多实例运行,如果需要一个应用的多个版本,可以在一个应用进程中运行多个实例,而不必部署多个 Web 服务器(将在 Flask 部署中介绍)

创建 Flask app 写在 project/__init__.py 中:​​​​​​​

from flask import Flaskfrom .config import configfrom . import models, routesdef create_app(config_name='default'):    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_APP=project
  • Windows 命令行

set FLASK_APP=project
  • Powershell

$env:FLASK_APP="project"

然后在项目目录的上一层目录下执行命令,启动项目:

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 CTRL+C to quit)

设置启动参数

前面工厂方法可以定义一些参数,如何来指定呢?其中一种方法是设置环境变量 FLASK_APP,例如将 congfig_name 参数设置为 testing:

  • Linux 或者 Mac

export FLASK_APP=project:create_app('testing')
  • Windows 命令行

set FLASK_APP=project:create_app('testing')
  • powershell

$env:FLASK_APP="project:create_app('testing')"
  • project 是 Flask app 所在的模块名,与上面直接写 project 一样

  • 冒号(:)后即为工厂方法的名,并且将参数带入

您可能已经想到,这种方式可以解决工厂方法名不是默认 create_app 的情况了,例如工厂方法名为 myapp_factory,以 Linux 环境为例:

export FLASK_APP=project: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)

  • JSON,app.config.from_json(jsonfilename)

总结

今天介绍了一个简单的 Flask 项目化结构,并利用之前做过的数据持久化的练习,做了项目化后的代码说明,并且说明了按功能和按业务两种项目组织方式,最后介绍了 Flask 项目中配置的方式。总之 Flask 是一个宽松的,简单的 Web 框架,每个人都可打造自己的一套项目构建方式,不过对于刚开始接触的同学,或者为了交流方便,还是有必要了解一下一般的组织方式,希望对您有所启发。

最后,示例代码中提供了较为完整的例子,其中还有如何自定义数据库初始化命令的例子,请您参考。

相关文章:

Flask 项目结构

前面我们了解了 Flask 框架的特性和一些用法,比如创建一个简单应用、做些页面,以及增加鉴权模块等,如果要将 Flask 用于实际项目开发,还需要了解一下 Flask 项目结构。 Flask 是一个轻量级的 Web 框架,扩展性强&#…...

云计算在IT领域的发展和应用

文章目录 云计算的发展历程云计算的核心概念云计算在IT领域的应用1. 基础设施即服务(IaaS):2. 平台即服务(PaaS):3. 软件即服务(SaaS): 云计算的拓展应用结论 &#x1f3…...

8年测试经验之谈 —— 接口自动化测试requests

1.什么是requests? requests是一个Python第三方库,处理URL资源特别方便 2.安装requests pip3 install requests 如果遇到Permission denied安装失败,请加上sudo重试 3.使用requests 3.1get请求方法 3.1.1基本的get请求 import reques…...

求助:vue从后端获取数据,如何对获得的数据进行拆分?

从后端获取数据格式如下: { "count": 3, "lists": [ { "id": 2, "name_id": 4, "name": "4: 2201030019: 张四", }, { …...

html5拖拽文件上传需阻止默认事件

至少阻止下列3个事件的默认行为才能实现文件拖拽上传 var bdocument.getElementById(box) b.ondragenter(e)>{e.preventDefault()console.log(aaa,e.dataTransfer.files); } b.ondragover(e)>{e.preventDefault()console.log(bb,e.dataTransfer.files); }b.ondrop(e)>…...

深入剖析Kubernetes之Pod基本概念(一)

文章目录 Pod 中重要字段Pod 的生命周期 Pod,而不是容器,才是 Kubernetes 项目中的最小编排单位。将这个设计落实到 API 对象上,容器(Container)就成了 Pod 属性里的一个普通的字段。那么,到底哪些属性属于…...

idea 对JavaScript进行debug调试

文章目录 1.新增 JavaScript Debug 配置2.配置访问地址3.访问url. 打断点测试 前言 : 工作中接手别人的前端代码没有注释,看浏览器的network或者console切来切去,很麻烦,可以试试idea自带的javscript debug功能。 1.新增 JavaScript Debug 配…...

npm init

1、什么是npm init npm是开源 JavaScript 包管理器,允许 JavaScript 开发人员分享和重用代码。npm init是一种在创建新的npm包时使用的命令,它将提示你填写一些信息以便在package.json文件中创建初始配置。 2、为什么要使用npm init初始化项目 在node…...

微信小程序开发教学系列(6)- 数据缓存与本地存储

第六章 数据缓存与本地存储 在开发微信小程序时,我们通常会面临一个问题:如何在不重复请求接口的情况下,将数据保存在本地,提高用户体验并减少网络请求的次数。这就需要我们学会使用数据缓存和本地存储的技巧。本章将介绍在微信小…...

跟我学c++中级篇——模板的基础术语说明

一、类模板术语 1、模板的特化 模板的特化也叫具体化&#xff0c;非常容易理解&#xff0c;就是把模板中的模板参数给定具体的类型。看下面的例子&#xff1a; //模板 template <typename T,typname N> class Data {}; //特化 template<> class Data<int,int&…...

最新Win10离线安装.NET Framework 3.5的方法(附离线包2022/3/22)

win10系统安装软件时&#xff0c;可能需要.net framework3.5的运行环境&#xff0c;当我们安装某些软件的时候会提示“你的电脑上的应用需要使用以下Windows功能:.NET Framework 3.5(包括.NET 2.0和3.0)。如果系统默认的是4.0以上的版本&#xff0c;当软件需要.net framework3.…...

最新docker多系统安装技术

在Ubuntu操作系统中安装Docker 在Ubuntu操作系统中安装Docker的步骤如下。 1&#xff0e;卸载旧版本Docker 卸载旧版本Docker的命令如下&#xff1a; $ sudo apt-get remove docker docker-engine docker.io 2&#xff0e;使用脚本自动安装 在测试或开发环境中&#xff0…...

系统架构设计高级技能 · 云原生架构设计理论与实践

系列文章目录 系统架构设计高级技能 软件架构概念、架构风格、ABSD、架构复用、DSSA&#xff08;一&#xff09;【系统架构设计师】 系统架构设计高级技能 系统质量属性与架构评估&#xff08;二&#xff09;【系统架构设计师】 系统架构设计高级技能 软件可靠性分析与设计…...

Springboot集成RocketMQ——简单使用

目录 1.MQ选型 2.RocketMQ基本架构 3.Springboot集成RocketMQ 4.顺序消息 5.延时消息 6.事务消息 1.MQ选型 目前市面上的MQ选型&#xff1a;主要分为3个类型 Kafka&#xff1a;吞吐量大&#xff0c;且性能好&#xff0c;集群高可用&#xff1b;会丢失数据&#xff0c;功…...

第一百二十四回 Flexible组件

文章目录 概念介绍使用方法示例代码 我们在上一章回中介绍了扩展内容相关的知识&#xff0c;本章回中将介绍 Flexible组件.闲话休提&#xff0c;让我们一起Talk Flutter吧。 概念介绍 我们在前面章回中介绍了扩展列表相关的内容&#xff0c;当页面中其它组件和扩展列表一起使…...

关于stm32推挽带有上下拉电阻的思考、IO口驱动能力是什么

1、发现推挽带有上下拉电阻 1.1、stm32手册 记忆中推挽是不需要上下拉的&#xff0c;没关注过&#xff0c;但是我真的理解上下拉吗&#xff0c;下图来自stm32f4的中文版和英文版的数据手册&#xff0c;没有翻译错&#xff0c;就是“推挽带有上下拉的能力”。 1.2、查找相关信…...

考研408 | 【操作系统】 内存管理

内存的基础 内存和内存的作用&#xff1a; 几个常用的数量单位&#xff1a; 指令的工作原理&#xff1a; 问题&#xff1a;如何将指令中的逻辑地址转换为物理地址&#xff1f; 解决办法&#xff1a;装入的三种方式 1.绝对装入 2.可重定位装入 3.动态重定位 从写程序到程…...

C# 工厂模式

一、概述 工厂模式&#xff08;Factory Pattern&#xff09;是一种创建型设计模式&#xff0c;它提供了一种创建对象的最佳方式。在C#中&#xff0c;工厂模式通过定义一个公共接口或抽象类来创建对象&#xff0c;而具体的对象创建则由工厂类来实现。 工厂模式主要包含三个角色…...

在云服务器上安装Jenkins

说明&#xff1a;Jenkins是一个部署项目的平台&#xff0c;通过Jenkins可以省去从项目开发–>部署项目之间的所有流程&#xff0c;做到代码提交即上线。本文介绍在云服务CentOS上安装Jenkins。 前提 安装Jenkins之前&#xff0c;先要在云服务上安装JDK、Maven、Git&#x…...

一文了解SpringBoot中的IOC

目录 1.什么是IOC 2.IOC容器 3.创建IOC容器 4.装配Bean到IOC容器 5.依赖注入 1.什么是IOC IOC&#xff1a;Inversion of Control 控制反转 Sping中我们把一个个对象称为Bean&#xff0c;以前我们实例一个对象的时候&#xff0c;都会直接New一个 而在Spring中&#xff0…...

地震勘探——干扰波识别、井中地震时距曲线特点

目录 干扰波识别反射波地震勘探的干扰波 井中地震时距曲线特点 干扰波识别 有效波&#xff1a;可以用来解决所提出的地质任务的波&#xff1b;干扰波&#xff1a;所有妨碍辨认、追踪有效波的其他波。 地震勘探中&#xff0c;有效波和干扰波是相对的。例如&#xff0c;在反射波…...

突破不可导策略的训练难题:零阶优化与强化学习的深度嵌合

强化学习&#xff08;Reinforcement Learning, RL&#xff09;是工业领域智能控制的重要方法。它的基本原理是将最优控制问题建模为马尔可夫决策过程&#xff0c;然后使用强化学习的Actor-Critic机制&#xff08;中文译作“知行互动”机制&#xff09;&#xff0c;逐步迭代求解…...

React Native 开发环境搭建(全平台详解)

React Native 开发环境搭建&#xff08;全平台详解&#xff09; 在开始使用 React Native 开发移动应用之前&#xff0c;正确设置开发环境是至关重要的一步。本文将为你提供一份全面的指南&#xff0c;涵盖 macOS 和 Windows 平台的配置步骤&#xff0c;如何在 Android 和 iOS…...

三维GIS开发cesium智慧地铁教程(5)Cesium相机控制

一、环境搭建 <script src"../cesium1.99/Build/Cesium/Cesium.js"></script> <link rel"stylesheet" href"../cesium1.99/Build/Cesium/Widgets/widgets.css"> 关键配置点&#xff1a; 路径验证&#xff1a;确保相对路径.…...

FFmpeg 低延迟同屏方案

引言 在实时互动需求激增的当下&#xff0c;无论是在线教育中的师生同屏演示、远程办公的屏幕共享协作&#xff0c;还是游戏直播的画面实时传输&#xff0c;低延迟同屏已成为保障用户体验的核心指标。FFmpeg 作为一款功能强大的多媒体框架&#xff0c;凭借其灵活的编解码、数据…...

鸿蒙中用HarmonyOS SDK应用服务 HarmonyOS5开发一个医院挂号小程序

一、开发准备 ​​环境搭建​​&#xff1a; 安装DevEco Studio 3.0或更高版本配置HarmonyOS SDK申请开发者账号 ​​项目创建​​&#xff1a; File > New > Create Project > Application (选择"Empty Ability") 二、核心功能实现 1. 医院科室展示 /…...

鸿蒙中用HarmonyOS SDK应用服务 HarmonyOS5开发一个医院查看报告小程序

一、开发环境准备 ​​工具安装​​&#xff1a; 下载安装DevEco Studio 4.0&#xff08;支持HarmonyOS 5&#xff09;配置HarmonyOS SDK 5.0确保Node.js版本≥14 ​​项目初始化​​&#xff1a; ohpm init harmony/hospital-report-app 二、核心功能模块实现 1. 报告列表…...

涂鸦T5AI手搓语音、emoji、otto机器人从入门到实战

“&#x1f916;手搓TuyaAI语音指令 &#x1f60d;秒变表情包大师&#xff0c;让萌系Otto机器人&#x1f525;玩出智能新花样&#xff01;开整&#xff01;” &#x1f916; Otto机器人 → 直接点明主体 手搓TuyaAI语音 → 强调 自主编程/自定义 语音控制&#xff08;TuyaAI…...

工业自动化时代的精准装配革新:迁移科技3D视觉系统如何重塑机器人定位装配

AI3D视觉的工业赋能者 迁移科技成立于2017年&#xff0c;作为行业领先的3D工业相机及视觉系统供应商&#xff0c;累计完成数亿元融资。其核心技术覆盖硬件设计、算法优化及软件集成&#xff0c;通过稳定、易用、高回报的AI3D视觉系统&#xff0c;为汽车、新能源、金属制造等行…...

华为云Flexus+DeepSeek征文|DeepSeek-V3/R1 商用服务开通全流程与本地部署搭建

华为云FlexusDeepSeek征文&#xff5c;DeepSeek-V3/R1 商用服务开通全流程与本地部署搭建 前言 如今大模型其性能出色&#xff0c;华为云 ModelArts Studio_MaaS大模型即服务平台华为云内置了大模型&#xff0c;能助力我们轻松驾驭 DeepSeek-V3/R1&#xff0c;本文中将分享如何…...