Django 过滤器父级,其中所有子值都符合条件

Django filter parent where ALL child values meet criteria

基于这些模型:

class Job(models.Model):
    status = models.CharField(max_length=30)

class Task(models.Model):
    job = models.ForeignKey('Job', related_name='tasks')
    status = models.CharField(max_length=30)

我需要一个查询 return 每个 Job.status 为空且 ALLTask.status 为 [=24] 的作业=].

对于上下文,当所有 Task.status 都完成时,将在每个兄弟 Task 中的值之间进行比较,直到所有兄弟 Task 完成后才应执行此操作设置为 "COMPLETE",因此查询将 return 那些完整的。

我们可以使用 Exists 子查询:

from django.db.models import Exists, OuterRef, Q

Job.objects.filter(
    <b>~Exists(</b>
        Task.objects.filter(~Q(status='COMPLETE'), job_id=OuterRef('pk'))
    <b>)</b>,
    status=None
)

这将导致如下查询:

SELECT <i>app_name</i>_job.*
FROM <i>app_name</i>_job
WHERE NOT EXISTS (
  SELECT U0.id, U0.job_id, U0.status
  FROM <i>app_name</i>_task U0
  WHERE NOT U0.status = COMPLETE
    AND U0.job_id = <i>app_name</i>_job.id
  )
  AND <i>app_name</i>_job.status IS NULL)

之前,您需要先注释,然后过滤:

from django.db.models import Exists, OuterRef, Q

Job.objects<b>.annotate(</b>
    all_complete=~Exists(
        Task.objects.filter(~Q(status='COMPLETE'), job_id=OuterRef('pk'))
    )
<b>)</b>.filter(all_complete=True, status=None)

如果一个Job没有任何任务,那么所有个任务(还有none)都算完成,所以这样[=如果 statusNone.

,结果中也会列出 11=]