Flask是一个基于Python实现的、基于MVC设计模式的、轻量级的Web开发框架,也被称为“微框架”,因为它使用简单的核心,用扩展来增加其他功能。
Flask流行的主要原因:
现在我们从零开始搭建项目环境
在项目根目录执行
bash# Windows/macOS/Linux 通用
python -m venv venv
执行后,项目里会多出一个 venv 文件夹
激活虚拟环境
Windows(命令提示符 CMD)
bashvenv\Scripts\activate
Windows(PowerShell)
bash.\venv\Scripts\Activate.ps1
macos/linux
bashsource venv/bin/activate
|---app // 应用入口集合 | ├---__init__.py | └---http |---config // 应用配置文件 | ├---__init__.py | ├---config.py | └---default_config.py |---internal // 应用所有内部文件夹 | ├---core // LLM核心文件,集成LangChain、LLM、Embedding等非逻辑的代码 | | |---agent | | |---chain | | |---prompt | | |---model_runtime | | |---moderation | | |---tool | | |---vector_store | | └---... | ├---exception // 通用公共异常目录 | | ├---__init__.py | | ├---exception.py | | └---... | ├---extension // Flask扩展文件目录 | | ├---__init__.py | | ├---database_extension.py | | └---... | ├---handler // 路由处理器、控制器目录 | | ├---__init__.py | | ├---account_handler.py | | └---... | ├---middleware // 应用中间件目录,包含校验是否登录 | | ├---__init__.py | | └---middleware.py | | └---... | ├---migration // 数据库迁移文件目录,自动生成 | | ├---versions | | └---... | ├---model // 数据库模型文件目录 | | ├---__init__.py | | ├---account.py | | └---... | ├---router // 应用路由文件夹 | | ├---__init__.py | | ├---router.py | | └---... | ├---schedule // 调度任务、定时任务文件夹 | | ├---__init__.py | | └---... | ├---schema // 请求和响应的结构体 | | ├---__init__.py | | └---... | ├---server // 构建的应用,与app文件夹对应 | | ├---__init__.py | | └---... | ├---service // 服务层文件夹 | | ├---__init__.py | | ├---oauth_service.py | | └---... | ├---task // 任务文件夹,支持即时任务+延迟任务 | | ├---__init__.py | | └---... |---pkg // 扩展包文件夹 | ├---__init__.py | |---oauth | | ├---__init__.py | | ├---github_oauth.py | | └---... | └---... ├---storage // 本地存储文件夹 ├---test // 测试目录 ├---venv // 虚拟环境 ├---.env // 应用配置文件 ├---.env.development // 开发环境配置文件 ├---.env.production // 生产环境配置文件 ├---.env.testing // 测试环境配置文件 ├---.gitignore // 配置git忽略文件 ├---requirements.txt // 第三方包依赖管理 └---README.md // 项目说明文件
在config下创建config.py
python#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
@Time : 2026/5/27 21:39
@Author: sql668
@File : config.py
"""
import os
from typing import Any
from dotenv import load_dotenv
from config.default_config import DEFAULT_CONFIG
def _get_env(key: str) -> Any:
"""从环境变量中获取配置项,如果找不到择返回默认值"""
return os.getenv(key, DEFAULT_CONFIG[key])
def _get_bool_env(key: str) -> bool:
"""从环境变量中获取布尔值配置项,如果找不到择返回默认值"""
value = _get_env(key)
return value.lower() == "true" if value is not None else False
class Config:
"""配置类"""
def __init__(self):
# 关闭wtf的csrf保护
self.WTF_CSRF_ENABLED = _get_bool_env("WTF_CSRF_ENABLED")
# print("WTF_CSRF_ENABLED", )
# 配置数据库配置
self.SQLALCHEMY_DATABASE_URI = _get_env("SQLALCHEMY_DATABASE_URI")
self.SQLALCHEMY_ENGINE_OPTIONS = {
'pool_size': _get_env("SQLALCHEMY_POOL_SIZE"),
'pool_recycle': _get_env("SQLALCHEMY_POOL_RECYCLE"),
}
self.SQLALCHEMY_ECHO = _get_bool_env("SQLALCHEMY_ECHO")
@staticmethod
def load_config():
"""根据环境变量加载对应配置"""
env = os.getenv('APP_ENV', 'development')
env_files = {
'development': '.env.development',
'testing': '.env.testing',
'staging': '.env.staging',
'production': '.env.production',
}
env_file = env_files.get(env, '.env')
if os.path.exists(env_file):
load_dotenv(env_file, override=True)
else:
load_dotenv('.env', override=True)
class DevelopmentConfig(Config):
"""开发环境配置"""
DEBUG = True
TESTING = False
class TestingConfig(Config):
"""测试环境配置"""
DEBUG = True
TESTING = True
class ProductionConfig(Config):
"""生产环境配置"""
DEBUG = False
TESTING = False
# 配置映射
config_by_name = {
'development': DevelopmentConfig,
'testing': TestingConfig,
'staging': DevelopmentConfig, # 预发布可以复用开发配置
'production': ProductionConfig,
}
def get_config():
"""获取当前环境的配置类"""
env = os.getenv('APP_ENV', 'development')
print('env:', env)
# 先加载环境变量
Config.load_config()
# 返回对应的配置类
return config_by_name.get(env, DevelopmentConfig)
default_config.py
pythonDEFAULT_CONFIG = {
"SQLALCHEMY_DATABASE_URI": "",
"SQLALCHEMY_POOL_SIZE": 30,
"SQLALCHEMY_POOL_RECYCLE": 3600,
"SQLALCHEMY_ECHO": "True",
"WTF_CSRF_ENABLED": "False"
}
在internal/handler下创建文件app_handler.py
python#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
@Time : 2026/5/21 23:04
@Author: sql668
@File : app_handler.py
"""
import os
import uuid
from dataclasses import dataclass
from injector import inject
@inject
@dataclass
class AppHandler:
"""应用控制器"""
def ping(self):
return {"ping": "pong"}
__init__.py
python#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
@Time : 2026/4/8 23:00
@Author: sql668
@File : __init__.py.py
"""
from .app_handler import AppHandler
__all__ = [
"AppHandler"
]
在internal/router下创建文件router.py
python#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
@Time : 2026/5/21 23:08
@Author: sql668
@File : router.py
"""
from dataclasses import dataclass
from flask import Flask, Blueprint
from injector import inject
from internal.handler import AppHandler
@inject # 自动注入,必须有构造函数
@dataclass # 该注解的作用是自动生成构造函数,不用手动去写
class Router:
"""路由"""
app_handler: AppHandler
def __init__(self, app_handler: AppHandler):
self.app_handler = app_handler
def register_router(self, app: Flask):
"""注册路由"""
# 1. 创建一个蓝图
bp = Blueprint("llmops", __name__, url_prefix="")
# 2. 将url 与对应的控制器方法做绑定
# app_handler = AppHandler()
bp.add_url_rule("/ping", methods=["GET"], view_func=self.app_handler.ping)
# 3. 在应用上去注册蓝图
app.register_blueprint(bp)
--init__.py
python#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
@Time : 2026/4/8 23:02
@Author: sql668
@File : __init__.py.py
"""
from .router import Router
__all__ = ['Router']
在internal/server下创建http.py
python#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
@Time : 2026/5/21 23:22
@Author: sql668
@File : http.py
"""
import os
from flask import Flask
from internal.router import Router
from config import Config
class Http(Flask):
"""Http服务引擎"""
def __init__(self, *args, conf: Config,db: SQLAlchemy,router: Router, **kwargs):
super().__init__(*args, **kwargs)
# 初始化应用配置
self.config.from_object(conf)
# 初始化数据库
db.init_app(self)
# 注册应用路由
router.register_router(self)
python#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
@Time : 2026/6/2 17:48
@Author: sql668
@File : module.py
"""
from flask_migrate import Migrate
from injector import Module, Binder
from internal.extension.database_extension import db
from internal.extension.migrate_extension import migrate
from pkg.sqlalchemy import SQLAlchemy
class ExtensionModule(Module):
"""扩展模块的依赖注入"""
def configure(self, binder: Binder) -> None:
binder.bind(SQLAlchemy, to=db)
binder.bind(Migrate, to=migrate)
在app/http下创建app.py
python#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
@Time : 2026/5/21 23:27
@Author: sql668
@File : app.py
"""
from injector import Injector
from internal.router import Router
from internal.server import Http
from config import Config, get_config
from app.http.module import ExtensionModule
# 先加载环境变量
get_config()
conf = Config()
# 将 .env 加载到环境变量中
# dotenv.load_dotenv()
injector = Injector([ExtensionModule])
app = Http(__name__, conf=conf,router=injector.get(Router))
if __name__ == "__main__":
app.run(host="0.0.0.0", port=8080, debug=True)
bashpython -m app.http.app
## requirements
安装依赖
```bash
pip install --no-deps pipreqs
pip install yarg==0.1.9 docopt==0.6.2
生成requirements.txt
bashpipreqs --ignore venv --force
## 补充 ### Flask-wtf Flask-wtf 是基于 wtforms 封装的 Flask 插件,支持 CSRF保护、快速提取数据、自定义验证规则及 wtforms的所有规则。 wtforms 支持提取的数据类型:布尔值、日期、文本、时间、浮点数、邮箱、文件、音频、整数、自定义数据类型等。 wtforms 支持校验的规则:必填、长度、邮箱、正则、范围、 UUID 、数据可选、 URL 等。 安装 ```bash pip install -U Flask-WTF
使用 在internal/schema下创建app_schema.py
python#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
@Time : 2026/5/27 21:12
@Author: sql668
@File : app_schema.py
"""
from flask_wtf import FlaskForm
from wtforms import StringField
from wtforms.validators import Length, DataRequired
class CompletionReq(FlaskForm):
"""基础聊天请求验证"""
# 必填,长度最大为2000
query = StringField('query', validators=[
DataRequired(message="用户的提问是必填"),
Length(max=2000, message="用户的提问最大长度是2000"),
], description="用户输入")


本文作者:繁星
本文链接:
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!