如何在我的Conversation模型上进行适当的过滤?

时间:2016-03-14 16:03:16

标签: 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.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')

我已经personnes一个ManyToManyField(而不仅仅是srcdst)所以我可以拥有尽可能多的Person会话。

我的问题是当我有这样的2个人时:

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()

但结果看起来像是“那些 那两个人之间的对话”。

我该怎么办?

4 个答案:

答案 0 :(得分:0)

这应该有效:

c = Conversation.objects.filter(personnes=p_src).filter(personnes=p_dst).distinct()

答案 1 :(得分:0)

您需要2个步骤才能实现此目的。首先,确保personnes的数量等于您要匹配的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)

答案 2 :(得分:0)

这是一个工作解决方案,根本没有优化,所以如果你有任何其他更好的解决方案,我就是你的男人!

# 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')

答案 3 :(得分:0)

我尝试找到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)

我希望它可以帮到你。请告诉我它不是。