首页 > 解决方案 > Django ORM左连接到同一张表

问题描述

我在 django 项目中有一个自定义权限系统,可以将任何用户链接到任何特定模型实例以授予对该对象的权限。它比这更复杂,但归结为:

class Permission(models.Model):
    user = models.ForeignKey(User)
    content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE)
    object_id = models.PositiveIntegerField()
    content_object = GenericForeignKey('content_type', 'object_id')

我想查询任何用户的所有权限,这些权限链接到特定用户已被授予权限的相同 content_object(s)。换句话说,有问题的用户想要查看还有谁对他们所做的任何相同对象拥有权限。

在 SQL 中,以下方法可以解决问题:

SELECT 
    perm1.* 
FROM app_permission perm1 
LEFT JOIN app_permission perm2 
    ON perm2.user_id = 12345
    AND perm1.content_type_id = perm2.content_type_id 
    AND perm1.object_id = perm2.object_id 
WHERE perm2.id IS NOT NULL;

是否有可能在 django ORM 中实现这一点?

标签: sqldjangodjango-modelsdjango-orm

解决方案


您可以使用Exists子查询 [Django-doc],这可能是您打算做的,所以:

from django.db.models import Exists, OuterRef

Permission.objects.filter(
    Exists(Permission.objects.filter(
        user_id=12345, content_type_id=OuterRef('content_type_id'), object_id=OuterRef('object_id')
    ))
)

另一种选择可能是对模型使用“一二技巧”ContentType并使用:

from django.db.models import F

Permission.objects.filter(
    content_type__permission__user=12345,
    content_type__permission__id__isnull=False,
    content_type__permission__object_id=F('object_id')
)

推荐阅读