我正在使用 django-mppt 来允许项目模型在我的应用程序中有父项目(并且任务属于项目)。每个项目都有一个状态,我正在尝试查询所有处于活动状态且其祖先也都处于活动状态的项目(最终,查询属于这些项目的任务)。
楷模
class Project(MPTTModel):
...
parent = TreeForeignKey('self', null=True, blank=True)
STATUS_CHOICES = (
(1, 'Active'),
(2, 'Paused'),
(3, 'Completed'),
)
status = models.PositiveSmallIntegerField(choices=STATUS_CHOICES)
...
class Task(models.Model):
...
project = TreeForeignKey(Project, null=True, blank=True)
...
原始 SQL
我已经设法构建了一个原始 SQL 查询,它可以让我获得所有处于活动状态且其祖先也都处于活动状态的项目。我通过为任何不活动的祖先构造一个 LEFT OUTER JOIN 来做到这一点,并检查结果是否为 NULL,即不存在不活动的祖先(不确定这是否是最好的方法)。
SELECT p.* FROM projects_project p
LEFT OUTER JOIN projects_project a -- join inactive ancestors
ON a.tree_id = p.tree_id AND a.lft <= p.lft AND a.rght >= p.rght -- must be MPTT ancestor
AND a.status != 1 -- must not be active
WHERE p.status = 1 AND a.id IS NULL -- i.e. is active and has no inactive ancestors
Django 查询?
是否可以将这个——或功能上等价的东西——写成 Django 查询?
我知道我可以使用Q 对象进行复杂的查找,并且我已经查看了F() 表达式......但是 F() 表达式似乎没有帮助,因为无法通过项目的外键访问项目的祖先,而是根据我对 MPTT 的理解,需要一个 JOIN 或带有基于 和 字段的过滤器的tree_id
子lft
查询rght
。
我想出了这个 Django 片段,假设我已经有一个 Project p 作为对象,我可以为该特定对象的任何非活动祖先构造一个 Django 查询:
Project.objects.filter(tree_id=p.tree_id, lft__lte=p.lft, rght__gte=p.rght).exclude(status=1)
但是然后我需要已经从数据库中检索到项目来检查它的祖先......
如何在连接或子查询中使用该片段作为过滤器的一部分,以便我可以在单个查询中检索所有相关项目(即活动且没有不活动的祖先),就像上面的原始 SQL 一样?
(那么,我如何查询属于没有非活动祖先的活动项目的所有任务?)