这可能是侮辱性的简单而且值得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')
让以下用户成像:
搜索文档的用户应该生成以下内容:
基本上,我正在精神上努力找出过滤器来返回我上面描述的查询集。有人有任何想法吗?
修改
感谢Ferdinands的回答,我能够通过他给我的开始坚持到我想要的东西。 首先,我们希望得到一个与我结识的人员名单,这是通过多对多关系进行反向查询:
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)
)
答案 0 :(得分:8)
这有点棘手,也许你正在寻找类似的东西:
>>> 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
)
)
)