Django prefetch_related过滤失效,预加载关联数据返回非指定用户记录
问题根因
你为Prefetch指定的用户过滤条件没有生效,核心原因是后续调用了.values()方法且通过双下划线inventoryCards__xxx直接读取关联表字段:该操作会触发Django直接对两张表执行SQL JOIN,完全绕过prefetch_related的预加载逻辑,你写的Prefetch过滤规则不会被应用到最终执行的SQL中,自然会返回所有用户的库存数据,出现同卡多条记录的问题。
解决方案
优先推荐放弃直接用values读取关联字段,通过预加载的模型实例手动构造返回数据,示例如下:
sql_int = "CAST((REGEXP_MATCH(number, '\d+'))[1] as INTEGER)" cards = magic_set_cards.objects.all().exclude(side='b').extra(select={'int': sql_int}) \ .prefetch_related(Prefetch('inventoryCards', queryset=inventory_cards.objects.filter(user_id=request.user.id))) \ .order_by('-set_id__releaseDate', 'set_id__name', 'int', 'number') # 手动构造返回字段 result = [] for card in cards: # 预加载的inventoryCards已过滤仅保留当前用户数据,最多存在1条 user_inventory = card.inventoryCards.first() result.append({ 'id': card.id, 'set_id__code': card.set_id.code, 'set_id__name': card.set_id.name, 'set_id__isOnlineOnly': card.set_id.isOnlineOnly, 'number': card.number, 'name': card.name, 'imageUri': card.imageUri, 'hasNonFoil': card.hasNonFoil, 'hasFoil': card.hasFoil, 'inventoryCards__nonfoil': user_inventory.nonfoil if user_inventory else 0, 'inventoryCards__foil': user_inventory.foil if user_inventory else 0 })
注意事项
- 若使用Django REST Framework,可直接在Serializer中读取预加载的关联库存数据,无需手动拼接字典
- 你代码中用到的
extra方法已被Django标记为不推荐使用,可替换为Django内置的Func表达式实现相同的数字提取逻辑,兼容性更强
内容的提问来源于stack exchange,提问作者Ross
相关产品推荐
相关产品推荐

