Django 中的多对多查找
这可能非常简单,值得 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 个是 私人(意味着只有朋友可以看到 它)。她是鲍勃的朋友,是 无视马洛里,态度冷漠 朝向夏娃(意思是没有存储 关系)。
- 马洛里有 2 份文件,均为公开文件 并且对每个人都冷漠。
- Bob 有 1 个公开文档 并且还冷漠地对待 每个人。
- 夏娃无视爱丽丝并且是 对 Mallory 和 Bob 漠不关心
搜索文档的用户应该产生以下结果:
- Bob 搜索文档应该 参见 6,因为爱丽丝已使他成为朋友 他可以查看她的私人信息 文件。
- 爱丽丝搜索文档应该 参见 4、鲍勃 1 和她的 3。她没有 请参阅 Mallory 的公开文件: 爱丽丝无视马洛里。
- 马洛里搜索文件看到 5 - Alice 的公共的,她自己的 2 和鲍勃 1.爱丽丝忽视她没有 与马洛里所看到的有关,只是 爱丽丝没有看到马洛里的 文档。
- 夏娃搜索文档看到 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)
)
This is probably insultingly simple and worthy of a Nelson Muntz laugh, but I'm having a real braindead moment tryng to make many to many connections across various model relationships.
I have the following models (simplified for your enjoyment!):
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')
Imaginging the following Users:
- Alice has 3 documents, 1 of which is
private (meaning only friends can see
it). She is friends with Bob, is
ignoring Mallory and is apathetic
towards Eve (meaning no stored
relationship). - Mallory has 2 documents, both public
and is apathetic towards everyone. - Bob has 1 document which is public
and is also apathetic towards
everyone. - Eve is ignoring Alice and is
apathetic to Mallory and Bob
Users searching for documents should produce the following:
- Bob searching for documents should
see 6, as Alice has made him a friend
and he can view her private
documents. - Alice searching for documents should
see 4, Bobs 1 and her 3. She doesn't
see Mallory's public documents as
Alice is ignoring Mallory. - Mallory searching for documents sees
5 - Alice's public ones, her own 2
and Bobs 1. Alice ignoring her has no
bearing on what Mallory can see, just
that Alice doesn't see Mallory's
docs. - Eve searching for documents sees 3 -
Mallory and Bob's public documents as
she has ignored Alice.
Basically, I'm having a mental struggle figuring out the filters to returning the querysets I described above. Anyone got any ideas?
EDIT
Thanks to Ferdinands answer below I was able to nut through to what I wanted with the start that he gave me.
First off, we want to get a list of people who have friended me which is a reverse lookup through the Many to Many relationship:
friendly_authors = self.user.user_friends.all()
Get all the people I've ignored:
my_ignored = UserProfile.objects.get(user=self.user).ignored.all()
Get a list of docs I can view - docs which are viewable, mine, or written by people who have friended me but whom I haven't ignored:
docs = Document.objects.filter(
(Q(viewable=True) | Q(author=self.user) | Q(author__in=friendly_authors))
& ~Q(author__in=my_ignored)
)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
这有点棘手,也许您正在寻找类似的东西:
这会生成以下 SQL(我对原始输出进行了一些格式化):
It is a bit tricky, maybe you are looking for something like that:
This generates the following SQL (I did some formatting on the original output):