Django ORM 左连接到同一个 table
Django ORM Left Join onto same table
我在 Django 项目中有一个自定义权限系统,可以 link 任何用户向任何特定模型实例授予对该对象的权限。它比这更复杂,但归结为:
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')
我想查询任何用户的所有权限,这些权限被link编辑到特定用户已被授予权限的相同content_object。换句话说,有问题的用户想看看还有谁对他们所做的任何相同对象具有权限。
在 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 中实现这一点?
您可以使用 Exists
subquery [Django-doc] 这可能是您打算做的,所以:
from django.db.models import <strong>Exists, OuterRef</strong>
Permission.objects.filter(
Exists(Permission.objects.filter(
user_id=12345<strong>, content_type_id=OuterRef('content_type_id'), object_id=OuterRef('object_id')</strong>
))
)
另一种选择是对 ContentType
模型使用“一二技巧”并使用:
from django.db.models import <strong>F</strong>
Permission.objects.filter(
content_type__permission__user=12345,
content_type__permission__id__isnull=False,
<strong>content_type__permission__object_id=F('object_id')</strong>
)
我在 Django 项目中有一个自定义权限系统,可以 link 任何用户向任何特定模型实例授予对该对象的权限。它比这更复杂,但归结为:
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')
我想查询任何用户的所有权限,这些权限被link编辑到特定用户已被授予权限的相同content_object。换句话说,有问题的用户想看看还有谁对他们所做的任何相同对象具有权限。
在 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 中实现这一点?
您可以使用 Exists
subquery [Django-doc] 这可能是您打算做的,所以:
from django.db.models import <strong>Exists, OuterRef</strong>
Permission.objects.filter(
Exists(Permission.objects.filter(
user_id=12345<strong>, content_type_id=OuterRef('content_type_id'), object_id=OuterRef('object_id')</strong>
))
)
另一种选择是对 ContentType
模型使用“一二技巧”并使用:
from django.db.models import <strong>F</strong>
Permission.objects.filter(
content_type__permission__user=12345,
content_type__permission__id__isnull=False,
<strong>content_type__permission__object_id=F('object_id')</strong>
)