gpt4 book ai didi

django - Django 中的复杂反向查询

转载 作者:行者123 更新时间:2023-12-01 12:59:06 27 4
gpt4 key购买 nike

简而言之:我的模型是 B --> A <-- C,我想过滤 Bs 其中至少有一个 C> 存在,满足一些任意条件并且与 AB 相关。也感谢您帮助解决一些复杂的因素(见下文)。

详细信息:

我正在尝试创建一个通用模型来限制用户访问其他模型中的行。这是一个(简化的)示例:

class CanRead(models.Model):
user = models.ForeignKey(User)
content_type = models.ForeignKey(ContentType)
object_id = models.PositiveIntegerField()
content_object = generic.GenericForeignKey('content_type', 'object_id')

class Direct(models.Model):
...

class Indirect(models.Model):
direct = models.ForeignKey(Direct)
...

class Indirect2(models.Model):
indirect = models.ForeignKey(Indirect)
...

CanRead 关联到每个模型中的每一行是不可行的(在空间上成本太高),因此只有一些模型应该具有这种关联(例如 Direct以上)。在这种情况下,以下是我查看用户是否可以访问 Direct 的方法:

Direct.objects.filter(Q(canread__user=current_user), rest_of_query)

(不幸的是,这个查询将不起作用 - 至少在 1.2.5 中 - 因为通用 fk;任何对此的帮助将不胜感激,但有解决方法,真正的问题是接下来的内容)

其他人的可访问性将取决于他们与其他模型的关系。因此,如果 direct 是可访问的,则用户将可以访问 Indirect,如果 indirect__direct 是,则 Indirect2 将是,等等

我的问题是,我该如何执行此查询?我很想写这样的东西:

Indirect.objects.filter(Q(canread__content_object=F('direct'), canread__user=current_user), rest_of_query)

Indirect2.objects.filter(Q(canread__content_object=F('indirect__direct'), canread__user=current_user), rest_of_query)

但这不起作用(Django 期望 CanReadIndirect 之间存在关系——这并不存在——以便反向查询起作用)。如果我直接用 SQL 编写它,我会做类似的事情:

SELECT *
FROM indirect i
JOIN direct d ON i.direct = d.id
JOIN canread c ON c.object_id = d.id
WHERE
c.content_type = <<content type for Direct>> AND
c.user = <<current user>> AND
<<rest_of_query>>

但我无法将该查询转换为 Django。可能吗?如果不是,那么干扰最小的方法是什么(尽可能少地使用原始 SQL)?

感谢您的宝贵时间!

注意:提到的解决方法是不使用通用 fk... :( 我可以放弃 CanRead 模型并有许多 CanReadDirectCanReadDirect2CanReadDirect3 等。这是一个小麻烦,但不会对我的项目造成太大阻碍。

最佳答案

对于您给出的简单案例,解决方案很简单:

B.objects.filter(a__c__isnull=False)

对于实际查询,这是我的尝试:

Indirect.objects.filter(direct__id__in=
zip(*CanRead.objects.filter(
content_type=ContentType.objects.get_for_model(Direct)
).values_list('id'))[0])

但这种方式非常慢:您从一个查询集中提取 ID,然后使用

where id in (1, 2, 3, ... 10000)

这是非常慢的。我们在项目中的通用外键连接上遇到了类似的问题,因此决定求助于模型管理器中的原始查询。

class DirectManager(Manager):
def can_edit(self, user):
return self.raw(...)

我还建议查看 per-row permissions Django 1.3 中的框架。

关于django - Django 中的复杂反向查询,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7775535/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com