FastAPI + Django 双框架架构
FastAPI + Django 双框架架构
学习目标
理解 Khoj 如何将 FastAPI 和 Django 两个框架融合在一个应用中,各自的职责边界,以及中间件管道的组织方式。
项目实践
职责分工
Khoj 选择同时使用两个框架,各自扬长:
| 框架 | 职责 | 原因 |
|---|---|---|
| FastAPI | API 路由、WebSocket、流式响应 | 原生 async/await、现代 Python 类型注解、StreamingResponse |
| Django | ORM、数据模型、Migration、Admin、认证 | 成熟的 ORM + Migration 系统、Admin 面板、认证后端生态 |
启动流程
main.py 中的 run() 函数(约 200 行)是启动入口:
1. 解析 CLI 参数(host, port, anonymous-mode 等)2. 配置 Django settings3. 运行 Django migration:call_command("migrate")4. 收集静态文件:collectstatic5. 执行初始化逻辑:initialization()6. 启动 APScheduler 调度器7. 配置 FastAPI 路由8. 挂载 Django 为子应用:app.mount("/server", django_asgi_app)9. 配置中间件(auth → session → CORS → HTTPS redirect)10. 启动 uvicornDjango 子应用挂载
from django.conf import settingsfrom django.core.wsgi import get_wsgi_applicationfrom fastapi import FastAPI
# 创建 FastAPI 应用app = FastAPI()
# 挂载 Django 为子应用django_asgi_app = get_asgi_application()app.mount("/server", django_asgi_app)FastAPI 的 mount() 将 Django 的 ASGI 应用挂载到 /server 路径前缀下。所有 /server/* 的请求直接交给 Django 处理,其余路径由 FastAPI 路由处理。
中间件执行顺序
中间件的顺序至关重要:
# 1. 认证中间件 - 最先执行,建立用户上下文app.add_middleware(UserAuthenticationBackend)
# 2. Session 中间件 - 在认证之后,用于存储 session 数据app.add_middleware(SessionMiddleware)
# 3. CORS 中间件 - 在业务逻辑之前,处理跨域预检app.add_middleware(CORSMiddleware, ...)
# 4. HTTPS 重定向 - 最后,确保前面所有中间件都在 HTTPS 下运行# (通过 middleware 配置)为什么认证在 Session 之前? 因为认证中间件需要检查请求头中的 bearer token 或 session cookie 来确定用户身份,Session 中间件依赖认证结果来决定如何加载 session 数据。
共享数据库连接
FastAPI 和 Django 共享同一个 PostgreSQL 连接池。关键点是:
- Django ORM 是同步的,在 FastAPI 的 async 环境中需要通过
sync_to_async包装 - Khoj 的数据库适配器(
src/khoj/database/adapters/)提供了 async 版本的 CRUD 操作 ProcessLock模型用于确保索引操作等独占任务的线程安全
问题与规避
| 问题 | 影响 | 规避策略 |
|---|---|---|
| 同步 ORM 阻塞 async 事件循环 | 响应延迟 | 使用 sync_to_async 包装数据库操作;或提供原生 async 适配器 |
| 中间件顺序错误 | 认证绕过或 CORS 失败 | 严格按照 auth → session → CORS → HTTPS 顺序注册 |
| 启动时自动 migration 失败 | 应用无法启动 | 生产环境可通过环境变量禁用自动 migration |
| 双框架的配置分散 | 维护困难 | src/khoj/app/settings.py 统一管理 Django settings,CLI 参数覆盖关键配置 |
设计取舍
为什么不用纯 FastAPI + SQLAlchemy?
Django 的 ORM + Migration + Admin 是成熟且经过大量项目验证的组合。如果切换到 SQLAlchemy,需要自行实现 Migration 系统(如 Alembic)、管理面板、认证后端等。对于 Khoj 这种需要快速迭代的项目,Django 的”电池内置”哲学节省了开发时间。
为什么不用纯 Django?
Django 的 async 支持和 WebSocket 支持相对滞后。Khoj 的流式聊天响应和 WebSocket 实时通信在现代 FastAPI 中是原生能力,在 Django 中需要额外的配置和 workaround。