Djongo 不是 Django + MongoDB 的可靠选择,因其本质是 SQL 到 BSON 的运行时翻译器,无法正确处理复杂查询、数组嵌套、聚合及事务,导致语义断层和不可预测行为。

为什么 Djongo 不是 Django + MongoDB 的可靠选择
Djongo 声称“用 Django ORM 语法操作 MongoDB”,但实际落地时几乎必然踩坑。它不是驱动层适配,而是 SQL 到 BSON 的运行时翻译器——这意味着 filter()、exclude()、annotate() 等操作在复杂查询下会生成错误的聚合管道,或直接抛出 NotImplementedError。
常见错误现象包括:
FieldError: Unsupported lookup 'icontains' for CharField or join on the related field- 使用
__in查询嵌套列表时返回空结果,但无报错 -
order_by('-created_at')在含数组字段的文档上静默失效
根本原因在于:Django ORM 的抽象模型基于关系代数,而 MongoDB 是文档模型。Djongo 强行映射二者,导致语义断层。尤其在涉及 ArrayField、JSONField、聚合(Sum, Avg)或事务场景下,行为不可预测。
用 PyMongo 直连 MongoDB 更可控
绕过 ORM 抽象,用原生 pymongo 操作集合,反而更符合 MongoDB 的使用逻辑。Django 视图/管理命令中直接调用,不依赖模型定义,也避免了 Djongo 的中间翻译损耗。
立即学习“Python免费学习笔记(深入)”;
实操建议:
- 在
settings.py中配置连接:MONGODB_URI = "mongodb://localhost:27017/",用motor(异步)或pymongo.MongoClient(同步)初始化客户端 - 不要把集合包装成 Django Model;用
db["users"]直接操作,字段名和结构完全自由 - 查询时用
find({"status": "active", "tags.2": "vip"})这类原生语法,而非试图模拟filter(tags__2="vip") - 写入前手动校验数据结构(比如用
pydantic.BaseModel),别指望 Djongo 的CharField(max_length=100)能约束 MongoDB 文档
性能上,直连省去 Djongo 的 query 解析+重写环节,QPS 提升明显;兼容性上,所有 MongoDB 5.0+ 新特性(如 $setWindowFields、时间序列集合)可立即使用。
需要 ORM 风格?试试 MongoEngine 或 Beanie
如果真需要类 ORM 的声明式定义和链式查询,MongoEngine(同步)或 Beanie(异步 + Pydantic 原生支持)比 Djongo 更贴近 MongoDB 语义。
关键差异点:
-
MongoEngine的EmbeddedDocumentListField明确对应数组嵌套,不会混淆为关系表;queryset.filter(name__iexact="a")翻译为{name: /^a$/i},行为可预期 -
Beanie使用Document类定义 schema,支持find().sort("-created_at").limit(10),底层直接转成find()+sort()命令,无中间 DSL 层 - 二者都不尝试兼容 Django 的
ForeignKey或ManyToManyField,避免强行建模带来的反模式
注意:它们不集成进 Django Admin,默认不提供 manage.py migrate 流程——这不是缺陷,而是对文档数据库本质的尊重。
Django Admin 里显示 MongoDB 数据?别硬塞,换思路
试图让 Djongo 的模型出现在 Django Admin,往往导致页面加载卡死或列表空白。因为 Admin 默认调用 queryset.count() 和 queryset.all()[:10],而 Djongo 对 count() 的实现可能触发全表扫描或失败。
更务实的做法:
- 用
django.contrib.admin.ModelAdmin的get_queryset方法返回一个轻量封装对象(比如只含_id和关键字段的字典列表),不走 ORM 查询链 - Admin 的
change_view中,用pymongo单独查完整文档并渲染自定义模板,避开form = self.get_form(request)对模型字段的反射依赖 - 或者干脆放弃 Admin,用 FastAPI 写个轻量后台接口 + Vue 表单,对 MongoDB 来说,这比拧巴地套 Django Admin 更自然
真正容易被忽略的是:MongoDB 的索引策略、读写关注(read_preference)、分片键设计,这些都得在应用层显式控制——没有“自动迁移”帮你兜底,也没人替你决定该不该在 email 字段上建唯一索引。想省事,最后反而花更多时间 debug。










