私は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 クエリとして記述することは可能ですか?
複雑なルックアップに Q オブジェクトを使用できることを知っており、 F() 式を見てきましたが、プロジェクトの祖先がプロジェクトの外部キーからアクセスできない限り、F() 式は役に立たないようです。 、しかし、MPTTを理解する限り、tree_id
、lft
およびフィールドに基づくフィルターを使用したJOINまたはサブクエリが必要です。rght
私はこの Django スニペットを思いつきました。オブジェクトとしてプロジェクト p が既にある場合、その特定のオブジェクトの非アクティブな先祖に対して Django クエリを作成できます。
Project.objects.filter(tree_id=p.tree_id, lft__lte=p.lft, rght__gte=p.rght).exclude(status=1)
しかし、そのような祖先を確認するために、プロジェクトをデータベースから取得する必要があります...
そのスニペットを結合またはサブクエリのフィルターの一部として使用して、上記の生の SQL のように、単一のクエリで関連するすべてのプロジェクト (つまり、アクティブで非アクティブな祖先を持たない) を取得するにはどうすればよいですか?
(では、非アクティブな祖先を持たないアクティブなプロジェクトに属するすべてのタスクを照会するにはどうすればよいでしょうか?)