【问题标题】:Django ORM Left Join onto same tableDjango ORM左连接到同一张表
【发布时间】:2021-12-03 20:11:15
【问题描述】:

我在 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 中是否可以实现这一点?

【问题讨论】:

    标签: sql django django-models django-orm


    【解决方案1】:

    您可以使用Exists subquery [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')
    )

    【讨论】:

      猜你喜欢
      • 2023-04-04
      • 1970-01-01
      • 1970-01-01
      • 2012-02-01
      • 1970-01-01
      • 2020-05-18
      • 1970-01-01
      • 1970-01-01
      • 2020-11-03
      相关资源
      最近更新 更多