Django切换MongoDB后get_or_create查询报No exception message supplied错误
问题排查与解决方案
核心原因
你使用Django原生ORM对接MongoDB,大概率是用了Djongo作为数据库适配引擎,报错是因为MongoDB和关系型数据库的行为差异、以及Djongo本身的兼容bug导致异常被吞,没有抛出具体错误信息。
具体排查解决步骤
- 首先处理
order_number字段的唯一约束冲突:
PostgreSQL的唯一约束允许多条记录的该字段为NULL,但MongoDB的普通唯一索引不允许存在多个值为NULL的文档。你模型里order_number设置了unique=True且默认值为NULL,调用get_or_create创建新订单时,只要之前已经存在一条order_number为NULL的订单,就会触发唯一索引冲突,这是最常见的触发该错误的原因。
解决方法二选一:- 给
get_or_create补充order_number的默认生成逻辑,创建订单时直接生成唯一订单号,不要留空 - 手动在MongoDB中修改
order集合的order_number唯一索引,添加sparse: true属性,稀疏索引会跳过值为NULL的文档,和PostgreSQL的行为保持一致
- 给
- 修复Djongo的
get_or_create兼容bug:
旧版本Djongo对get_or_create的适配存在已知问题,可以先尝试安装稳定版本:pip install djongo==1.3.6
如果还是报错,可以把get_or_create拆分为查询+创建的两步逻辑,避开适配问题:def cartData(request): if request.user.is_authenticated and request.user.user_type == 'patient': patient = Patient.objects.select_related('user').get(user=request.user) # 拆分get_or_create逻辑 order_queryset = Order.objects.filter(patient=patient, complete=False) if order_queryset.exists(): order = order_queryset.first() created = False else: # 创建时必须传入生成好的唯一order_number,不要留空 order = Order.objects.create( patient=patient, complete=False, order_number=生成唯一订单号的函数() ) created = True items = order.cartitem_set.select_related('medicine').all() cartItems = order.get_cart_items - 检查数据库适配方案:
如果你没有使用Djongo,而是用的MongoEngine,需要注意不能继承Django原生的models.Model,要改为继承MongoEngine的Document类,原生Django ORM不支持非关系型数据库,直接使用会抛出未定义异常。 - 查看MongoDB服务日志:
如果以上操作都没有解决,可以直接查看MongoDB的运行日志,执行报错查询时数据库端的错误信息不会被Django吞掉,可以快速定位具体问题。
内容的提问来源于stack exchange,提问作者Kuldeep
相关产品推荐
相关产品推荐

