为什么在 2025 年我仍然选择 Django 构建 SaaS 项目

7 阅读1分钟

大家好,这里是架构资源栈!点击上方关注,添加“星标”,一起学习大厂前沿架构!

今天,Django 看起来仿佛“过时”了。Next.js、Supabase、Astro、T3 Stack 这些前端全家桶层出不穷,开箱即用,几小时内就能搭建起一个全栈应用,让你迅速交付价值。

但当我需要构建一个真正可控、结构清晰、易于长期维护的 SaaS 后端时,我依然首选 Django。

它或许不够“潮”,却足够可靠;加上合适的配套工具,就能迸发惊人实力。


现代全栈工具的优点

不可否认,Next.js 等方案做得很出色:

  • 前后端合一,代码集中管理
  • 一键部署到 Vercel,流程简洁
  • Prisma、Auth.js 等库快速上手

如果你在做:

  • 落地页
  • 原型演示
  • 低复杂度的 MVP

JavaScript 全家桶确实可以让你快速上线。但随着业务增长,项目中产生的种种混乱,也让人头疼不已——而 Django 在这方面表现更稳。


Django 的四大杀手锏

  1. 明确的项目结构

    • 模型(Models)、序列化器(Serializers)、视图(Views)、路由(URLs)一目了然
    • 新人加入后无需猜测,快速上手
  2. 严格且可控的数据模型

    • 复杂关系、事务、信号(Signals)等功能强大
    • 明确的数据库迁移流程,变更可回退
  3. 完善的权限体系

    • Django 自带的用户、组、权限系统
    • DRF(Django REST Framework)提供的 ViewSet、Permission 等组件
  4. 长期支持(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)
  1. 开启“轮换窗口”后,新密钥用于加密,旧密钥仍可解密
  2. 轮换结束后移除旧密钥,调用方无感知
  3. 基于 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 的惯用模式,也方便团队协作与测试。


资源推荐


总结:我也会使用 Next.js、T3、FastAPI、NestJS 等新兴框架,但当你需要可控性可维护性长线稳定支持时,Django 无可替代。希望这篇文章能帮你更好地评估技术选型,勇敢拥抱“龟速”背后的高效与可靠!

转自:mp.weixin.qq.com/s/wOdCbbutH…

本文由博客一文多发平台 OpenWrite 发布!