如果你关注我的 Github 号的话(好吧我赌你没关注,但欢迎互关),你应该会注意到我新近几天一直在给某个项目开 PR,疯狂 release,就是这玩意儿(话说你愿意给star 吗?)。
先大概介绍一下这个项目吧:给我们海中人做一个互联平台(航海家计划,将于今年 6 月正式发布,预计开发周期一年,明年同期公测并上线),而 Tinder 就是这个互联平台的后端。采用 FastAPI + pgsql + redis 为框架。
虽然说高三的学业其实非常繁忙,但我依然抽出很多时间去构想,如下部分(数据库架构设计图、API 目录设计图):
可以看到如果你单纯去绘制下蓝图,整个系统还是非常简单的,但如果你真的着手去实践,你就会发现,哇,我其实很菜(对,反正我很菜)。
我始终贯彻的一个开发理念是:先有后端才有前端,后端围绕数据,前端则着重用户体验。
所以首先要做的就是后端和数据部分!
在开发 Tinder 之前,我其实拥有相当稀少的 FastAPI 开发基础,所以构建出一个基本框架(导入 App,设置 CORS,启动应用)不成问题,但这之后呢?我的评价是我就像从零开始学,在此欢迎各位大佬指出值得改进的地方与问题。
因为 Tinder 使用 Python 开发,所以我并不能直接使用 prisma 来实现数据迁移与操作,但并不是什么大问题对吧。Tinder 的数据迁移思路源自于 Mix-Space 中的迁移方法(遍历已存在的记录并在 MongoDB 中检查是否有相应的记录,如果发现有则执行对应的文件,然后写入代码中防止后期重复执行),Tinder 使用了相同的思路,只不过将其迁移到了 Python+pysql
你可以使用 excalidraw 来大致的了解整个流程,应当很好理解:
算是个没多少用的功能,没什么意义,只是为了取代原有的print( ),美化下日志输出,方便查找错误日志云云。
代码写在下面
# ANSI 颜色代码
_GREEN = "\033[92m"
_ORANGE = "\033[38;5;208m"
_RED = "\033[91m"
_RESET = "\033[0m"
_LEVEL_CONFIG = {
"SUCCESS": (_GREEN, "[SUCCESS]"),
"WARNING": (_ORANGE, "[WARNING]"),
"ERROR": (_RED, "[ERROR]"),
}
def custom_log(log_level: str, log_content: str) -> None:
"""打印自定义颜色日志。
Args:
log_level: 日志级别,支持 'SUCCESS'、'WARNING'、'ERROR'(不区分大小写)。
log_content: 日志内容。
"""
level_key = log_level.upper()
color, label = _LEVEL_CONFIG.get(level_key, (_RESET, f"[{level_key}]"))
print(f"{color} {label} {log_content}{_RESET}")
这是我开发了几天下来最大的感受:我是菜鸡,我其实啥也不会。毕竟第一次去着手写这种相对较为大型的 API 来说,很多问题与标准我都要问AI 和交给 Agent 解决。
这是一个小细节,然而值得去打磨,以给后期开发奠定基础。
目前的目录结构是这样的,那天我问了ds很多问题:比如数据库连接器算不算 helper?firewall 应该放哪里?经过几次打磨,最终成了这样一个相对较为清晰的架构:
ORM 这个东西我经常在一些项目上见过,主打一个安全,预防 SQL 注入(我之前那个项目甚至手动拼接 sqlcommand,想想还是有点怕的),然而我对此并不熟悉,所以交给AI解决了。
DTO 我先前在 Mx-Space 的源码里见过,然而当时没有仔细了解。
DAO 则是我在与 ds聊天过程中了解的。
那么二者有什么区别呢:
DAO(数据访问对象)负责封装数据库的增删改查操作,关注的是“如何存储”数据;DTO(数据传输对象)则是一个简单的容器,用于封装需要传输的数据,关注的是“如何传递”数据。
好吧实际上我在正式开发之前是打算在某个 API 文件里直接调用数据库的,但实际开发如此正式,也算学到了。
这二者也是我先前很模糊的概念,现在大概明白了点,就是“餐厅里值班经理与服务”的关系。后者仅是前者调用的一种。
太好笑了,我一个人竟然需要查看AI写的《数据库使用指南》,好吧,我是菜鸡,我确实得学。
不想自己写,所以交给 AI 去写了,后期有文件要 Test 也交给 AI 吧。
目前 Tinder 已更新到了 V0.2.3,但实际建起的部分更多是辅助,API 部分除了/以外都没开发,任重而道远啊。
下次commit应当是高考完了
距离高考还剩 105 天,祝一切顺利。
Tinder/
├── .github/ # GitHub 配置目录
│ └── workflows/ # GitHub Actions 工作流
│ ├── codeql.yml # CodeQL 代码安全扫描工作流
│ ├── docker-build.yml # Docker 镜像构建工作流
│ └── test.yml # 自动化测试工作流
├── core/ # 核心功能模块
│ ├── database/ # 数据库相关
│ │ ├── connection/ # 数据库连接管理
│ │ │ ├── db.py # SQLAlchemy 引擎与会话工厂(ORM 基类 Base)
│ │ │ └── redis.py # Redis 连接管理
│ │ ├── dao/ # 数据访问对象(Data Access Object)
│ │ │ ├── base.py # BaseDAO 基类,提供通用 CRUD 操作
│ │ │ ├── comments.py # 评论表 ORM 模型与 DAO
│ │ │ ├── favourites.py # 收藏表 ORM 模型与 DAO
│ │ │ ├── illegal_requests.py # 违规请求表 ORM 模型与 DAO
│ │ │ ├── personal_logs.py # 个人日志表 ORM 模型与 DAO
│ │ │ ├── relations.py # 用户关系表 ORM 模型与 DAO
│ │ │ ├── request_logs.py # 请求日志表 ORM 模型与 DAO
│ │ │ ├── song_arrangements.py # 歌曲编排表 ORM 模型与 DAO
│ │ │ ├── songs.py # 歌曲表 ORM 模型与 DAO
│ │ │ ├── stores_and_restaurants.py # 商店与餐厅表 ORM 模型与 DAO
│ │ │ ├── system_logs.py # 系统日志表 ORM 模型与 DAO
│ │ │ ├── system_reports.py # 系统报告表 ORM 模型与 DAO
│ │ │ ├── tags.py # 标签表 ORM 模型与 DAO
│ │ │ ├── tasks.py # 任务表 ORM 模型与 DAO
│ │ │ ├── tokens.py # 令牌表 ORM 模型与 DAO
│ │ │ ├── users.py # 用户表 ORM 模型与 DAO
│ │ │ ├── vote.py # 投票表 ORM 模型与 DAO
│ │ │ ├── wall_looking_for.py # 寻找墙贴表 ORM 模型与 DAO
│ │ │ └── wall_sayings.py # 说说墙贴表 ORM 模型与 DAO
│ │ └── migrations/ # 数据库迁移管理
│ │ ├── SQL/ # SQL 迁移脚本目录
│ │ │ ├── alter_users_add_password.sql # 用户表新增密码字段
│ │ │ ├── initial_comments.sql # 评论表初始化
│ │ │ ├── initial_favourites.sql # 收藏表初始化
│ │ │ ├── initial_illegal_requests.sql # 违规请求表初始化
│ │ │ ├── initial_migration_user.sql # 用户表初始化
│ │ │ ├── initial_personal_logs.sql # 个人日志表初始化
│ │ │ ├── initial_relations.sql # 用户关系表初始化
│ │ │ ├── initial_request_logs.sql # 请求日志表初始化
│ │ │ ├── initial_song_arrangements.sql # 歌曲编排表初始化
│ │ │ ├── initial_songs.sql # 歌曲表初始化
│ │ │ ├── initial_stores_and_restaurants.sql # 商店与餐厅表初始化
│ │ │ ├── initial_system_logs.sql # 系统日志表初始化
│ │ │ ├── initial_system_reports.sql # 系统报告表初始化
│ │ │ ├── initial_tags.sql # 标签表初始化
│ │ │ ├── initial_tasks.sql # 任务表初始化
│ │ │ ├── initial_tokens.sql # 令牌表初始化
│ │ │ ├── initial_vote.sql # 投票表初始化
│ │ │ ├── initial_wall_looking_for.sql # 寻找墙贴表初始化
│ │ │ └── initial_wall_sayings.sql # 说说墙贴表初始化
│ │ └── migration_history.py # 迁移脚本执行顺序列表
│ ├── helper/ # 通用辅助工具
│ │ └── ContainerCustomLog/ # 自定义日志模块
│ │ └── index.py # 带颜色与时间戳的控制台日志工具
│ └── middleware/ # 中间件
│ └── firewall/ # 防火墙/访问控制中间件
│ ├── config.py # 防火墙规则配置
│ ├── helpers.py # 防火墙辅助函数
│ ├── index.py # 对外暴露 FirewallMiddleware
│ └── middleware.py # 防火墙中间件实现(IP 封禁、限流等)
├── docs/ # 项目文档
│ └── database/ # 数据库相关文档
│ ├── db-migration.excalidraw # 数据库迁移流程图(Excalidraw 格式)
│ └── readme.md # 数据库说明文档
├── modules/ # 业务功能模块
│ └── index/ # 根路由模块
│ └── index.py # 根路由(GET /),返回系统信息
├── tests/ # 测试目录
│ ├── integration/ # 集成测试
│ │ ├── conftest.py # pytest 集成测试夹具配置
│ │ ├── test_api.py # API 接口集成测试
│ │ └── test_firewall.py # 防火墙中间件集成测试
│ └── unit/ # 单元测试
│ ├── test_custom_log.py # 自定义日志模块单元测试
│ ├── test_firewall_helpers.py # 防火墙辅助函数单元测试
│ └── test_index_router.py # 根路由单元测试
├── .env.example # 环境变量示例文件(数据库/Redis 配置模板)
├── .gitignore # Git 忽略规则
├── Dockerfile # Docker 镜像构建文件
├── LICENSE # 开源许可证
├── README.md # 项目说明文档(本文件)
├── db_migrate.py # 数据库迁移入口脚本(使用 psycopg2 执行 SQL)
├── docker-entrypoint.sh # Docker 容器启动脚本
├── pytest.ini # pytest 配置文件
├── requirements.txt # Python 依赖列表
└── server.py # FastAPI 应用入口,配置中间件与路由