《写给前端的python应用指南》系列:
- (一)快速构建 Web 服务器 - Flask vs Node.js 对比
书接上文,这一篇将会深入了解下Flask,这个轻量级的Web框架,非常适合用来构建小型应用和快速原型开发。但是,随着应用规模的扩大,我们往往会遇到代码膨胀和难以管理的问题(这个问题在几乎所有的开发中都会遇到。通过深入探讨Flask应用的结构,学会如何将其模块化设计,能帮助你更好地构建可扩展、易维护的大型Flask应用。
另外我发现不少全栈岗位,是以python和java作为后端的,Nodejs的有,但一般很少,甚至他们招熟练使用Nodejs的开发人员,进去后再全栈开发 - 相当于用前端的价格招全栈人员,而我就是这样的,然后我也这样招人,因为符合条件的人员真不多。但实践了一两年,发现重新培养全栈同事是很难的事情,不只是知识面广需要主动研究,还有就是上下文切换(代码允许在什么环境)。不如出个文章,至少看完本文,说明你对全栈开发是感兴趣,而不是被逼着学的 - 现在我再做导师一类的,也不会逼人学什么了,自己研究我的文章去
一、Flask应用的基本结构
Flask虽然是一个“微框架”,但它的结构非常灵活,允许你根据项目需求自由组织代码,是可以扩展到中大型应用。一个简单的Flask应用通常有如下结构:
/my_flask_app/app__init__.pyroutes.pymodels.pytemplates/static//instanceconfig.pyrun.py
这个结构和常用的后端应用差不多,例如express,也会有config、app、routes、models、public/static,用到模板引擎则有templates,万变不离其宗,虽然语言不同但做的事情或者目标相差无几 - CRUD,生成页面,读取数据,调用与整合接口数据
1. __init__.py
__init__.py
是Flask应用的核心,它负责初始化Flask应用及其配置、路由和数据库等部分。通常,我们会在这个文件中创建Flask实例,并进行应用相关的配置。
2. routes.py
routes.py
是定义应用路由的地方。Flask应用的每个URL都会映射到一个视图函数,而路由则是URL和视图函数的绑定。
3. models.py
models.py
通常用于定义数据库模型,尤其是在使用ORM(如SQLAlchemy)时,用于创建数据库表的模型类。
4. templates/
与static/
这两个文件夹分别用于存放HTML模板文件和静态资源(如CSS、JavaScript文件、图片等)。Flask使用Jinja2模板引擎来渲染HTML页面。
5. instance/config.py
config.py
用于存放应用的配置项,可以是数据库配置、API密钥、日志设置等。我们通常将配置文件放在instance
目录中,以保持安全性和灵活性。
6. run.py
run.py
是Flask应用的启动入口,运行Flask应用时,通常会通过该文件来启动应用。
二、如何实现Flask应用的模块化设计
随着项目规模的增长,单个文件会变得冗长且难以维护。为了提高代码的可读性和可扩展性,我们需要将Flask应用进行模块化。Flask允许我们使用“蓝图”(Blueprint)来实现这一点。蓝图是Flask的核心特性之一,它能够将应用分成多个模块,每个模块负责一个独立的功能或业务领域。
1. 创建蓝图
一个典型的Flask项目可以根据功能划分成多个模块,例如用户认证、文章管理、评论系统等。每个模块都可以定义一个蓝图。蓝图通过Flask.register_blueprint()
来注册到主应用上。
蓝图类似于一个子路由,抽象的route,除非挂载不起作用,和express的route类似
比较小的项目我个人并不推荐用,或许将各个处理方法整理,在使用的地方挂载就可以了
示例:创建一个用户模块的蓝图
# app/auth/routes.pyfrom flask import Blueprintauth = Blueprint('auth', __name__)@auth.route('/login')
def login():return "Login Page"@auth.route('/logout')
def logout():return "Logout Page"
在上面的代码中,我们定义了一个名为auth
的蓝图,并为其添加了/login
和/logout
两个路由。接下来,我们需要将这个蓝图注册到主应用中。
主应用中注册蓝图
# app/__init__.pyfrom flask import Flask
from .auth.routes import authdef create_app():app = Flask(__name__)app.register_blueprint(auth, url_prefix='/auth')return app
在create_app()
函数中,我们将auth
蓝图注册到主应用上,并为它指定了一个URL前缀/auth
。这样,/login
和/logout
的路由就变成了/auth/login
和/auth/logout
。
2. 模块化视图函数
除了路由,Flask的视图函数也可以进行模块化。对于大型项目,我们可以根据不同的功能将视图函数拆分到不同的文件中。这样做可以避免将所有代码堆积在一个文件里,增加代码的可读性。
仁者见仁智者见智,其实我是推荐视图在一个文件“挂载”,但仅仅是挂载,类似请求路由->处理函数的映射比表,不在这里写其它逻辑,对于整个应用的掌控更好,尤其是微服务应用
示例:将路由与视图分离
# app/auth/views.pyfrom .routes import auth@auth.route('/profile')
def profile():return "User Profile"
在这个例子中,我们将profile
视图函数从routes.py
中提取到了一个单独的views.py
文件中。这有助于将业务逻辑与路由定义分离,增强代码的可维护性。
3. 模块化模型和数据库操作
Flask和SQLAlchemy结合使用时,模型通常是存放在单独的models.py
中。然而,如果项目越来越大,多个模块可能会有不同的数据库模型。为了避免在一个文件中定义所有模型,可以将模型分开管理。
示例:模块化数据库模型
# app/auth/models.pyfrom . import dbclass User(db.Model):id = db.Column(db.Integer, primary_key=True)username = db.Column(db.String(80), unique=True, nullable=False)password = db.Column(db.String(120), nullable=False)
在models.py
文件中定义的模型类可以通过蓝图或应用来使用。每个模块都可以定义与其功能相关的模型,并在主应用中进行注册。
4. 配置与环境分离
为了更好地管理应用配置,Flask允许我们在不同的环境(开发、测试、生产)中使用不同的配置文件。在Flask中,我们通常使用config.py
来管理配置项,并通过from_object()
方法加载配置。
示例:加载配置文件
# app/__init__.pyimport os
from flask import Flaskdef create_app(config_name=None):app = Flask(__name__)# 默认加载开发环境配置app.config.from_object(config_name or 'config.DevelopmentConfig')return app
在不同的环境中,可以通过加载不同的配置文件来管理数据库连接、日志记录等。
三、总结
通过蓝图和模块化设计,Flask应用能够轻松地扩展和维护。无论是路由、视图函数还是数据库模型,都可以被拆分到不同的模块中,避免了代码的膨胀和管理困难。通过合理的模块化设计,你的Flask应用将变得更加清晰、灵活和易于维护。
在这篇文章中,我们重点介绍了Flask应用的基本结构以及如何通过蓝图实现模块化。希望通过这篇文章,你能够更好地理解Flask的架构设计,并在实际开发中应用这些技巧构建高效、可维护的Flask应用。