Django使用**kwargs过滤:循环字段过滤代码Shell有效运行时失效,求排查
问题分析与解决:Django QuerySet 过滤不生效的原因
你踩了一个Django QuerySet的经典小坑——QuerySet是惰性且不可变的,这也是你的代码在Shell里看似正常、实际运行却没效果的核心原因。
问题出在哪?
每次调用qs.filter(**filter)时,Django并不会修改原来的qs对象,而是返回一个全新的QuerySet实例,包含过滤后的结果。但你的代码里只是调用了filter,却没有把这个新的QuerySet重新赋值给qs,所以循环结束后,qs还是最初的Model.objects.all(),自然看不到过滤效果。
至于Django Shell里的“正常工作”,其实是Shell会自动打印每一行代码的返回值——你看到的是每次filter后生成的新QuerySet,但原有的qs根本没被修改。
修正后的代码
只需要把过滤后的新QuerySet重新赋值给qs就行(另外建议避免用filter做变量名,它是Python内置函数):
qs = Model.objects.all() fields_list = ['a', 'b', 'c'] for field in fields_list: filter_param = {field: 20} qs = qs.filter(**filter_param) return qs
额外补充:不同过滤逻辑的实现
上面的代码实现的是同时满足a=20、b=20、c=20的逻辑(链式过滤相当于AND关系)。如果你的需求是任意一个字段等于20(OR关系),那需要用Q对象来组合查询:
from django.db.models import Q qs = Model.objects.all() fields_list = ['a', 'b', 'c'] query = Q() for field in fields_list: query |= Q(**{field: 20}) # 用|符号表示OR逻辑 qs = qs.filter(query) return qs
内容的提问来源于stack exchange,提问作者user7804233
相关产品推荐
相关产品推荐

