Django使用distinct()后调用in_bulk()报字段非唯一错误如何解决
问题解决方法
报错原因
该报错的触发原因是Django 3.1版本的in_bulk()方法仅会校验模型层字段定义的唯一性属性,不会感知QuerySet前置的distinct()逻辑已经保证了查询结果中foreign_key_id的唯一性。distinct()搭配in_bulk()的相关支持是在更高版本Django中引入的,3.1版本尚未兼容该特性。
可行修改方案
- 方案一:手动构造等效字典(最稳妥,无版本依赖)
直接遍历去重后的QuerySet生成键值对,效果和in_bulk()完全一致:
queryset = MyModel.objects.order_by("foreign_key_id").distinct("foreign_key_id") bulk_result = {obj.foreign_key_id: obj for obj in queryset}
- 方案二:升级Django版本
如果可以升级依赖,将Django升级到3.2及以上正式版本即可通过in_bulk()的校验,原有QuerySet写法不需要调整。 - 方案三:绕过唯一性校验(不推荐)
如果必须在Django 3.1环境下使用in_bulk(),可以先提取结果的主键列表后调用in_bulk()(默认使用主键查询,不会触发唯一性校验),再手动映射到外键ID:
queryset = MyModel.objects.order_by("foreign_key_id").distinct("foreign_key_id") pk_list = queryset.values_list("pk", flat=True) pk_map = MyModel.objects.in_bulk(pk_list) bulk_result = {obj.foreign_key_id: obj for obj in pk_map.values()}
该方案性能不如第一种,非必要不建议使用。
内容的提问来源于stack exchange,提问作者Josh
相关产品推荐
相关产品推荐

