如果你最近接手过一个跑了两三年的 Django 项目,大概会有一种感觉:框架本身一直在迭代,但真正的复杂度从来不在框架,而在那些历史遗留的模型关系、迁移文件、Celery 任务和没人敢乱动的数据表里。最近几个月,团队里陆续有人把 AI 编程工具接进 IDE,生成代码的速度确实快了不少。可等代码进入评审阶段,画风就变了——一堆看起来很像官方文档要求的 ORM 查询、凭空生成的序列化字段,还有跨模块直连 import,最后合并前消耗的时间反而更长了。
这让我想起 Django 社区里一位核心贡献者 Paolo Melchiorre 在公开分享中常做的一件事:他不急着推荐新工具,反而会追问一句——你打算怎么维护它?作为长期参与 Django 开发、也在各种开源活动里做过 workshop 的人,他关注的并不是某个 AI 工具能不能生成一段 Django 代码,而是 AI 进入开源工作流之后,谁来定义“这段代码真的可以合并”。
这些年我慢慢形成了自己的判断:AI 对 Django 开发者的价值,不是把写代码的时间变成零,而是把大家从样板代码里解放出来,去处理模型关系、业务规则和代码评审这些真正需要人的事情。开源项目真正稀缺的从来不是代码,而是负责任的审阅者。
1. 为什么 Django 是观察“AI + 开源”的最佳样本
1.1 Django 的“魔法”与 AI 的“不确定性”正面碰撞
Django 是一个约定大于配置、充满“魔法”的框架。ORM、Admin、Form、信号、中间件,每个功能都有默认的工作方式。你在生成代码时如果不知道这些隐藏约定,很容易产出看起来正确、跑起来有问题、甚至带权限泄漏风险的代码。
AI 代码生成器的底层逻辑是“学会很多常见写法,然后按高概率生成”。在快速迭代的项目里,这种模式表现不错;但在 Django 这种强约定框架里,高概率不等于正确。例如,一个模型可以设置 Meta.ordering,也可以手动 order_by,AI 可能忽略中间表里 through 参数,或者对多对多字段直接叠 filter。这些在编译期不会报错,只有数据量上来了才暴露。
所以 Django 的特殊性在于:它有一套稳定的“公约数”,AI 的产出只有被这个公约数约束才有意义。这也是不少国内团队在偏传统的管理系统里依然优先选择 Django 的原因:它把“约定”提前固定好,让团队协作更容易对齐。如果不能理解这种约束,AI 生成的 Django 代码就会成为下一轮技术债的起点。
1.2 开源项目维护者真正担心的不是代码量
Django 生态里,多数核心贡献者同时也是开源维护者。Paolo 所在的社区长期讨论的一个问题是:贡献者数量增加了,但有效维护时间没有增加。AI 把代码生成成本降下来之后,PR 数量会继续上升,但每个 PR 的质量、测试覆盖、文档和兼容性说明,仍然需要人来看。
这里有一个容易被忽略的判断:AI 没有减少“审阅”这个稀缺动作,反而放大了它。开源项目真正的瓶颈是维护者的注意力。AI 生成越多的代码,维护者需要做的审阅工作就越多;如果不能把审阅变成有模板、有检查清单、有自动化门禁的流程,社区就很容易被低质量贡献淹没。
Django 项目之所以适合观察这件事,是因为它的社区极其重视向后兼容和“不该出现意外的魔法”。任何打破约定、忽略迁移成本或污染全局命名空间的贡献,都会被严格拒绝。这正是 AI 时代最需要保留的工程纪律。
2. AI 在 Django 开发里真正的价值,不是替你写代码
2.1 模型设计与 ORM 查询:在“信息密度高”的任务上表现最好
Django 开发中最耗时间的部分,往往不是写视图,而是想清楚数据模型。AI 在这里的辅助价值很高,因为它可以把常见字段、choices、unique_together 等样板快速补全。
但模型设计是不可逆成本很高的工作。AI 可以很快给出一个多对多中间表方案,比如“用户订阅频道”的模型。但中间表叫什么名字、是否加 unique_together、外键级联策略怎么设,这些都必须由人确认。先给 AI 足够的约束条件,再让它生成,通常比让它自由发挥可靠得多。
ORM 查询也一样。让 AI 解释 select_related 和 prefetch_related 的区别,并快速生成两种写法,效率很高。但碰到 delete、update 这类批量操作时,AI 常常不会主动说清楚级联策略、信号触发和事务边界。实际落地时,最好先在小数据集上验证,再看数据库执行计划,而不是只看代码“像不像官方文档”。N+1 问题在数据量小时骗过所有人,一旦数据增长,就会变成线上事故。
2.2 视图、序列化与测试:节省的是重复劳动,不是质量责任
视图、Form、序列化器里的样板逻辑,AI 确实能生成得很快。但权限控制、字段校验、异常回滚这些一旦出问题,往往不是编译期能发现的。我的建议是:AI 生成的视图代码,先检查装饰器、权限类、过滤器,再检查输入是否被二次验证。
测试用例反而值得多让 AI 写。它很擅长从函数签名里补边界条件,虽然不会全对,但能帮你覆盖常规输入。迁移文件是另一个坑:AI 生成的 migration 大概率能跑,但遇到数据迁移、批量更新、复杂索引调整,就必须人工 review。它把数据库结构的变更固化进版本历史,一旦错误,比代码错误难修得多。
2.3 一个简单的判断表:哪些能交给 AI,哪些必须人来定
| 任务 | AI 辅助程度 | 人需要确认的重点 |
|---|---|---|
| 生成模型字段样板 | 高 | 关系设计、字段语义、业务约束 |
| 编写 filter/serializer | 中 | 权限、过滤条件、字段暴露范围 |
| 生成测试用例 | 高 | 断言是否有意义、是否覆盖真实场景 |
| 生成数据迁移 | 低 | 数据一致性、可回滚性 |
| 大型重构建议 | 中 | 拆模块时机、API 兼容性、迁移路径 |
这张表不是让你禁止 AI 做某些事,而是提醒:AI 生成越多的部分,人的判断越要前置到“能不能用”这个层级,而不是停留在“能不能编译”。
3. 从“生成一段代码”到“接进生产环境”,还差几块拼图
3.1 先想清楚:同步调用还是异步任务?
如果要在 Django 项目里接一个大模型 API,最常见的错误是在视图里同步发起 HTTP 请求。这会让请求线程在几十秒内被占用。开发环境看不出问题,生产环境一有并发,数据库连接池和 worker 就会被拖垮。
常见做法是放入异步队列。Celery 或 django-q 都可以,原则是:请求进入视图后立即返回任务 ID,后台任务完成后通过回调、轮询或 WebSocket 通知前端。这里给出一个 Celery 任务的最小示意,实际版本和队列配置需要按项目环境调整:
注意:这里只演示任务层的调用方式。Celery 的 broker、队列名称、并发策略需要结合项目环境另行配置。
# tasks.py from celery import shared_task import httpx from django.conf import settings @shared_task(bind=True, max_retries=3, default_retry_delay=15) def call_llm_for_summary(self, user_content: str): payload = { "model": "your-model-name", "messages": [{"role": "user", "content": user_content}], "temperature": 0.2, } try: resp = httpx.post( "https://api.example.com/v1/chat/completions", json=payload, headers={"Authorization": f"Bearer {settings.LLM_API_KEY}"}, timeout=20.0, ) resp.raise_for_status() return resp.json()["choices"][0]["message"]["content"] except httpx.TimeoutException: # self.retry 会重新入队,countdown 让任务稍后再试 raise self.retry(countdown=30)这段代码里,API Key 必须来自 settings 和环境变量,不能硬编码在文件里。模型名称、超时时间和重试次数,也要按你对接的服务来配置。
3.2 超时、重试、幂等与数据隔离
大模型接口有天然的不确定性。超时、限流、返回格式变化都可能发生。因此工程上要提前做好四件事:
- 设置合理的超时时间,普通对话生成在 20 到 60 秒以内,超过就失败重试。
- 设计重试策略,区分哪些错误值得重试,哪些错误重试也没用。
- 做用户维度幂等,避免同一个请求被重复提交时创建多个任务。
- 对用户输入脱敏,不要把身份证号、手机号、完整邮箱等隐私信息原样塞进 Prompt。
尤其要强调最后一点。即使你用的是私有化部署模型,也建议只传业务必要字段,并在日志接收端过滤掉可能包含敏感信息的字段。如果你的业务必须调用外部服务,这一步就更加不能省。
特别提醒:不要把用户完整隐私数据直接传入外部模型请求,哪怕目标是私有化服务。
3.3 代码报错时的排查顺序
如果一段 AI 生成的 Django 代码在本地跑不通,我会按这个顺序排查:
- 先看报错发生在哪一层:URL 路由、视图函数、ORM 查询还是数据库迁移。
- 再确认 Django 是否“认识”这段代码:App 是否注册在 INSTALLED_APPS,模型是否被 import,迁移文件是否存在。
- 再看数据库层:表结构是否和模型一致,连接配置、权限、当前 Django/Python 版本是否匹配。
- 最后才检查代码本身的逻辑:外键参数、字段类型、查询表达式是否合理。
这个顺序的核心是:先确认框架认不认识这段代码,再确认数据库支不支持,最后才怀疑逻辑本身