You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Django QuerySet反向引用过滤:筛选关联Choice的已发布Question

高效筛选符合条件的Question QuerySet

针对你的需求,直接用Django ORM的查询语法就能一次性完成过滤,避免遍历带来的性能问题,以下是几种可行的方案:

方案1:利用外键非空过滤+去重

如果你的Choice模型有指向Question的外键(假设外键字段名为question),可以直接通过choice__isnull=False过滤出有关联选项的问题,同时结合发布时间条件:

from django.utils import timezone
from .models import Question

valid_questions = Question.objects.filter(
    pub_date__lt=timezone.now(),
    choice__isnull=False
).distinct()
  • 加distinct()是因为一个问题如果对应多个选项,查询结果会重复,去重后得到唯一的问题集合
  • 整个查询只会触发一次数据库请求,性能远高于遍历查询

方案2:通过注解计数过滤

用annotate给每个问题添加关联选项的计数,再过滤计数大于0的结果:

from django.db.models import Count
from django.utils import timezone
from .models import Question

valid_questions = Question.objects.filter(
    pub_date__lt=timezone.now()
).annotate(
    choice_count=Count('choice')
).filter(
    choice_count__gt=0
)
  • 这种方式不需要额外去重,因为annotate会按Question分组统计选项数量
  • 同样是单次数据库查询,结果更直观(可以直接拿到每个问题的选项数)

方案3:子查询判断存在性

用Exists子查询明确判断当前问题是否存在关联的选项,逻辑更清晰:

from django.db.models import Exists, OuterRef
from django.utils import timezone
from .models import Question, Choice

valid_questions = Question.objects.filter(
    pub_date__lt=timezone.now(),
    Exists(Choice.objects.filter(question=OuterRef('pk')))
)
  • 这种写法和方案1性能接近,但可读性更强,适合复杂关联场景

关于你之前的报错

你提到用pk报错,大概率是写法有误,比如错误使用了choice__pk__exists这类语法,以上三种方案都不需要手动处理pk,ORM会自动处理关联条件。

内容的提问来源于stack exchange,提问作者wsys

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.09 03:55:25