Django QuerySet __in过滤空列表时如何忽略过滤返回全量结果
问题说明
原有过滤代码如下:
queryset = self.filter( brand_id__in=( UserObjectPermission.objects.filter( content_type=brand_ctype, user=user, ).values_list('object_pk') ) )
该逻辑存在不符合预期的表现:当没有匹配content_type=brand_ctype, user=user条件的UserObjectPermission对象时,brand_id__in会接收空查询集作为过滤范围,最终返回空结果。
预期需要实现的逻辑为:
- 若上述权限子查询无匹配结果:忽略
brand_id__in过滤规则,返回全部对象 - 若上述权限子查询存在至少1条匹配结果:执行
brand_id__in过滤,仅返回品牌ID在权限范围内的对象
实现代码
核心思路是先判断权限查询集是否存在有效记录,再动态追加过滤条件,避免空__in查询导致结果为空的问题,代码如下:
# 构造用户品牌权限子查询 brand_permissions = UserObjectPermission.objects.filter( content_type=brand_ctype, user=user ).values_list("object_pk", flat=True) queryset = self.all() # 仅当存在有效权限记录时,才执行品牌范围过滤 if brand_permissions.exists(): queryset = queryset.filter(brand_id__in=brand_permissions)
实现说明
- 调用
exists()做前置判断只会生成EXISTS类型的SQL查询,不需要拉取全量权限数据,性能开销极低 - 子查询添加
flat=True参数,直接返回扁平化的ID值列表,适配__in过滤的参数格式要求,避免嵌套结构导致的匹配错误 - 无匹配权限记录时直接返回全量查询集,完全符合预期逻辑
内容的提问来源于stack exchange,提问作者johny
相关产品推荐
相关产品推荐

