大家好,这里是架构资源栈!点击上方关注,添加“星标”,一起学习大厂前沿架构!
今天,Django 看起来仿佛“过时”了。Next.js、Supabase、Astro、T3 Stack 这些前端全家桶层出不穷,开箱即用,几小时内就能搭建起一个全栈应用,让你迅速交付价值。
但当我需要构建一个真正可控、结构清晰、易于长期维护的 SaaS 后端时,我依然首选 Django。
它或许不够“潮”,却足够可靠;加上合适的配套工具,就能迸发惊人实力。
现代全栈工具的优点
不可否认,Next.js 等方案做得很出色:
- 前后端合一,代码集中管理
- 一键部署到 Vercel,流程简洁
- Prisma、Auth.js 等库快速上手
如果你在做:
- 落地页
- 原型演示
- 低复杂度的 MVP
JavaScript 全家桶确实可以让你快速上线。但随着业务增长,项目中产生的种种混乱,也让人头疼不已——而 Django 在这方面表现更稳。
Django 的四大杀手锏
-
明确的项目结构
- 模型(Models)、序列化器(Serializers)、视图(Views)、路由(URLs)一目了然
- 新人加入后无需猜测,快速上手
-
严格且可控的数据模型
- 复杂关系、事务、信号(Signals)等功能强大
- 明确的数据库迁移流程,变更可回退
-
完善的权限体系
- Django 自带的用户、组、权限系统
- DRF(Django REST Framework)提供的 ViewSet、Permission 等组件
-
长期支持(LTS)
- 官方发布的长期维护版本
- 社区稳定、生态成熟
表面看起来 Django 似乎“上手慢”,但正因为它“慢工出细活”,才能在项目演进中保持上限。
API Key 授权:Django 外的“地狱”体验
在我第一次用 Django 构建 API SaaS 时,分发 API Key 让我大呼“真香”,也遭遇性能瓶颈。以下几点,是我不使用 JWT 作为 API Key 的原因:
1. JWT 天生“短命”
- 通常只签发 15 分钟到 1 小时的临时令牌
- 刷新靠 Refresh Token,需额外逻辑
- 一旦签发,除非使用黑名单,否则无法撤回
API Key 往往需要机器或第三方长期调用,JWT 的短期设计并不适合。
2. 容易“过度编码”
{
"sub": "org_abc",
"role": "super",
"scopes": ["read", "write"],
"feature_flags": ["beta_search"],
"tenant_id": "xyz"
}
把业务逻辑塞进令牌,一旦规则变动,就要改生成逻辑,安全风险和维护成本都大增。理想的 API Key 应该是不透明、简单,所有元数据保存在服务端,由服务端决定授权。
3. 难以平滑轮换
- 切换签名密钥后,所有旧有 JWT 全部失效
- 客户端集成瞬间“断头”
- 必须额外实现 Key Registry、Key ID、灰度轮换等机制
而一个好的 API Key 系统,应支持多活密钥、优雅轮换、细粒度权限和调用限流。
我如何打造 drf-simple-api-key
发现 Django REST Framework 的 djangorestframework-api-key
包安全性不错,但基于 Django 密码哈希框架,校验时速度较慢。一次简单的请求可能要耗费数秒。
优化思路:使用 Python cryptography
库中的 Fernet 多密钥轮换,既保证加密安全,又能实现平滑密钥轮换。
from cryptography.fernet import MultiFernet, Fernet
# 当前密钥和旧密钥
current = Fernet(b'CURRENT_SECRET_KEY')
previous = Fernet(b'OLD_SECRET_KEY')
# 支持自动解密旧密钥
f = MultiFernet([current, previous])
# 加密新 API Key
encrypted = f.encrypt(b"api-key:my-user-123")
# 解密任何版本的密钥
decrypted = f.decrypt(encrypted)
- 开启“轮换窗口”后,新密钥用于加密,旧密钥仍可解密
- 轮换结束后移除旧密钥,调用方无感知
- 基于 Django 原生权限体系,新增使用量统计、限流等功能
结果:请求耗时从 2.5 秒降至 100ms 以下。
Django 架构带来的可扩展性
Django 借助 Python 的类继承、方法重写和 super()
,让功能扩展既优雅又可维护。例如,在 drf-simple-api-key
中:
class IsActiveEntity(BasePermission):
message = "Entity is not active."
def has_permission(self, request, view):
return request.user.is_active
class HasActiveSubscription(IsActiveEntity):
message = "Entity 无效或无有效订阅。"
def has_permission(self, request, view):
if not super().has_permission(request, view):
return False
return getattr(request.user, "has_active_subscription", False)
层层叠加、职责单一,既符合 Django 的惯用模式,也方便团队协作与测试。
资源推荐
- Django 官方文档(docs.djangoproject.com/en/5.2/)
- Thinkster 的 Django 进阶课程(thinkster.io/topics/djan…
- TestDriven 的 TDD Django + DRF + Docker 项目(testdriven.io/courses/tdd…
- Will Vincent 的 LearnDjango 教程(learndjango.com)
总结:我也会使用 Next.js、T3、FastAPI、NestJS 等新兴框架,但当你需要可控性、可维护性和长线稳定支持时,Django 无可替代。希望这篇文章能帮你更好地评估技术选型,勇敢拥抱“龟速”背后的高效与可靠!
本文由博客一文多发平台 OpenWrite 发布!