Django 如何对我的对话模式进行适当的筛选?
我有两个简单的模型:Django 如何对我的对话模式进行适当的筛选?,django,django-models,Django,Django Models,我有两个简单的模型: class Message(BaseModel): src = models.ForeignKey('Personne', related_name='message_src') dst = models.ForeignKey('Personne', related_name='message_dst') is_read = models.BooleanField(default=False) message = models.TextFie
class Message(BaseModel):
src = models.ForeignKey('Personne', related_name='message_src')
dst = models.ForeignKey('Personne', related_name='message_dst')
is_read = models.BooleanField(default=False)
message = models.TextField(null=True, blank=True,
verbose_name=_(u'Messages'))
class Conversation(BaseModel):
personnes = models.ManyToManyField(Personne, related_name='conversations')
messages = models.ManyToManyField(Message, related_name='conversations')
我被任命为人员
aManyToManyField
(而不仅仅是src
和dst
),这样我就可以拥有对话所需的任何人员
我的问题是当我有两个这样的人时:
p_src = Personne.objects.get(user=self.request.user)
# i've got id_dst somewhere before
p_dst = Personne.objects.get(pk=id_dst)
我想找回“只有那两个人的对话”
目前我正在做的是:
c = Conversation.objects.filter(
personnes__in=[p_src, p_dst]).distinct()
但是结果看起来像是“两个人中有一个人的谈话”
我应该怎么做?这应该可以:
c = Conversation.objects.filter(personnes=p_src).filter(personnes=p_dst).distinct()
要实现这一点,您需要两个步骤。首先,确保Personne
的计数等于要匹配的Personne
的数量。然后针对每个人员
实例筛选该字段:
from django.db.models import Count
personnes = [p_src, p_dst]
result = Conversation.objects.annotate(c=Count('personnes')).filter(c=len(personnes))
for personne in personnes:
result = result.filter(personnes=personne)
这里有一个有效的解决方案,根本没有优化,所以如果你有其他更好的解决方案,我就是你的人
# filter all conversations where there are 2 participants and
# (1) src is part of them
convs_src = Conversation.objects.annotate(c=Count('personnes'))\
.filter(c=2)\
.filter(personnes__in=[p_src])
# (2) dst is part of them
convs_dst = Conversation.objects.annotate(c=Count('personnes'))\
.filter(c=2)\
.filter(personnes__in=[p_dst])
# ... then take the intersection, which should always be "one":
convs = set(list(convs_src)).intersection(list(convs_dst))
if len(convs): # get() = pour avoir un objet (!= QuerySet)
c = Conversation.objects.get(pk=convs[0])
else:
raise Exception('should never ever happen')
我会尝试找到所有的对话,其中p_src和p_dst扮演着某种角色
conversations_where_two_are_in = Conversations.objects.all().filter(
Q(personnes = p_src)|
Q(personnes = p_dst)
)
扔掉所有其他人参与的对话。我会找到除了这两个我们感兴趣的人以外的所有人,并把他们列在一个名单上
list_of_other_personnes = Personnes.objects.all().exclude(
personnes = p_src,
personnes = p_dst,
)
我会把他们排除在我们两人的谈话之外
conversations_between_only_two = conversations_where_two_are_in.exclude(
personnes__in = list_of_other_personnes)
我希望它能帮助你。请让我知道不是这样。试着删除->中的..filter(personnes=[p\u src,p\u dst])。distinct()
如果我尝试(已经完成了:)
)我得到:int()参数必须是字符串或数字,而不是“list”
我正在考虑做相反的事情:从Person开始,比如“给我这两个人所有对话的交集”如果我尝试你的解决方案,我会有一个明显的Python错误:“关键字参数重复”,如果我尝试c=Conversation.objects.filter(personnes=p_src.filter(personnes=p_dst.distinct())
I get'QuerySet'对象没有“personnes”属性
对。我编辑了我的答案。尝试链接过滤器
确定?错误看起来像是您试图访问…过滤器(personnes=p_src)。persones
您确定p_src
是Personne
模型吗(创建一个只有外键的空模型给用户
)。因为在这种情况下,消息是合乎逻辑的:您不能询问“组”“=persones只等于一个Person
model我不知道,但它不一定有效。我刚刚使用了您的count
和anotate
示例使我自己的版本有效(参见我的答案).所以我给你投票,这样你就不会投反对票了。但是你真的尝试过你的解决方案吗?你能说明什么不起作用吗?我没有你的确切模型设置,但我以前用过。你可以只做一个empy Personne模型,有一个字段:userHi的外键,你做3个查询,我的解决方案做2个。我不知道哪一个是最快的。你怎么认为?