Django中的多对多查找

Posted

技术标签:

【中文标题】Django中的多对多查找【英文标题】:Many to many lookups in Django 【发布时间】:2010-11-22 01:07:54 【问题描述】:

这可能非常简单,值得 Nelson Muntz 大笑,但我真的想在各种模型关系中建立多对多的联系。

我有以下模型(为了您的享受而简化了!):

class Document(models.Model):
    title = models.CharField(max_length=200)
    author = models.ForeignKey(User, blank=True)
    content = models.TextField(blank=True)
    private = models.BooleanField(default=False)

class UserProfile(models.Model):
    user = models.ForeignKey(User, unique=True)
    friends = models.ManyToManyField(User, symmetrical=False, 
                                     related_name='user_friends')
    ignored = models.ManyToManyField(User, symmetrical=False, 
                                     related_name='user_ignored')

对以下用户进行成像:

Alice 有 3 个文档,其中 1 个是 私人(意味着只有朋友可以看到 它)。她是鲍勃的朋友,是 无视马洛里并且冷漠 朝着夏娃(意味着没有存储 关系)。 Mallory 有 2 个文档,都是公开的 对所有人都冷漠。 Bob 有 1 个公开的文档 并且对 大家。 夏娃无视爱丽丝, 对马洛里和鲍勃冷漠

搜索文档的用户应提供以下内容:

Bob 搜索文档应该 见 6,因为爱丽丝已经让他成为朋友 他可以查看她的私人信息 文件。 Alice 搜索文档应该 见 4,鲍勃 1 和她的 3。她没有 见马洛里的公开文件为 爱丽丝无视马洛里。 Mallory 搜索文档时看到 5 - Alice 的公开的,她自己的 2 和 Bobs 1. Alice 无视她没有 与马洛里能看到的东西有关,只是 爱丽丝没有看到马洛里的 文档。 Eve 搜索文档时看到 3 - 马洛里和鲍勃的公开文件为 她忽略了爱丽丝。

基本上,我在寻找过滤器以返回我上面描述的查询集时遇到了精神上的挣扎。有人有什么想法吗?

编辑

感谢费迪南德在下面的回答,我能够从他给我的开始就明白我想要什么。 首先,我们想要获得一个通过多对多关系反向查找与我成为朋友的人的列表:

friendly_authors = self.user.user_friends.all()

把所有我忽略的人都找出来:

my_ignored = UserProfile.objects.get(user=self.user).ignored.all()

获取我可以查看的文档列表 - 可以查看的文档、我的文档或由与我成为朋友但我没有忽略的人编写的文档:

docs = Document.objects.filter(
    (Q(viewable=True) | Q(author=self.user) | Q(author__in=friendly_authors))
     & ~Q(author__in=my_ignored)
)

【问题讨论】:

+1 以获得清晰的问题描述 :) 【参考方案1】:

这有点棘手,也许你正在寻找类似的东西:

>>> from django.db.models import Q
>>> me = User.objects.get(pk=1)
>>> my_friends = UserProfile.objects.get(user=me).friends.all()
>>> docs = Document.objects.filter(
...     Q(author=me) | (
...         Q(author__in=my_friends)
...         & ~Q(author__userprofile__ignored=me)
...     )
... )

这会生成以下 SQL(我对原始输出进行了一些格式化):

SELECT "myapp_document".*
FROM "myapp_document" WHERE (
    "myapp_document"."author_id" = %s
    OR (
        "myapp_document"."author_id" IN (
            SELECT U0."id" FROM "myapp_user" U0
            INNER JOIN "myapp_userprofile_friends" U1
                ON (U0."id" = U1."user_id")
            WHERE U1."userprofile_id" = %s
        )
        AND NOT (
            "myapp_document"."author_id" IN (
                SELECT U2."user_id" FROM "myapp_userprofile" U2
                INNER JOIN "myapp_userprofile_ignored" U3
                    ON (U2."id" = U3."userprofile_id")
                WHERE U3."user_id" = %s
            )
            AND "myapp_document"."author_id" IS NOT NULL
        )
    )
)

【讨论】:

谢谢你,你给了我我需要的东西,让我了解我想要返回的东西

以上是关于Django中的多对多查找的主要内容,如果未能解决你的问题,请参考以下文章

CASCADE 究竟如何与 Django 中的多对多字段一起工作

如何过滤和访问 Django QuerySet 中的多对多字段?

Django 管理中的多对多:选择无

从 Django 查询中的多对多关系中检索项目

使 ModelForm 与 Django 中的中间模型的多对多关系工作的步骤是啥?

列表中的多对多显示django