如何过滤Django多对多模型?筛选仅关联Pear的Plot及Input
解决Input筛选仅保留关联Pear类型Plot的问题
你的代码现在会选出所有至少关联一个Pear类型Plot的Input,但这些Input可能同时还绑定了Apple类型的Plot,所以结果里才会出现关联Apple的记录。我来帮你梳理问题并给出针对性的解决方案:
原代码的问题所在
你当前的代码逻辑是:
plots = Plot.objects.filter(fruittype__fruit="Pear") inputs = Input.objects.filter(plot__in=plots).distinct()
这段代码的作用是筛选出存在至少一个Pear Plot关联的Input,但并没有限制这些Input不能关联其他类型的Plot。举个例子:如果某个Input同时关联了Pear和Apple的Plot,它依然会被选进结果,当你查看这个Input的plot字段时,还是能看到Apple的Plot记录。
两种场景的解决方案
根据你的实际需求,我分两种情况给出方案:
场景1:只保留「所有关联Plot都是Pear类型」的Input
如果你想要的是那些完全没有关联非Pear类型Plot的Input,可以用exclude排除掉关联了非Pear Plot的记录:
# 先获取所有非Pear类型的Plot non_pear_plots = Plot.objects.exclude(fruittype__fruit="Pear") # 筛选出不关联任何非Pear Plot的Input inputs = Input.objects.exclude(plot__in=non_pear_plots).distinct()
或者用annotate统计非Pear Plot的数量,直接筛选数量为0的Input:
from django.db.models import Count, Q inputs = Input.objects.annotate( # 统计当前Input关联的非Pear Plot数量 non_pear_plot_count=Count('plot', filter=Q(plot__fruittype__fruit!="Pear")) ).filter(non_pear_plot_count=0)
场景2:保留关联了Pear Plot的Input,但仅加载这些Pear Plot
如果你只是希望在获取Input时,其关联的Plot集合仅显示Pear类型(而不是直接排除整个Input),可以用Prefetch来预筛选关联的Plot数据:
from django.db.models import Prefetch # 先定义Pear Plot的查询集 pear_plots_queryset = Plot.objects.filter(fruittype__fruit="Pear") # 筛选关联了Pear Plot的Input,并预加载仅包含Pear的Plot inputs = Input.objects.filter(plot__in=pear_plots_queryset).distinct().prefetch_related( Prefetch('plot', queryset=pear_plots_queryset) )
这样之后,当你访问input.plot.all()时,只会得到该Input关联的Pear类型Plot,不会出现Apple的记录。
额外确认
顺便帮你核对下模型关联:Plot关联Fruittype,Fruittype关联Fruit,所以fruittype__fruit="Pear"这个过滤条件是完全正确的,不用调整模型结构。
内容的提问来源于stack exchange,提问作者Linbreux
相关产品推荐
相关产品推荐

