复杂的Django查询集过滤,涉及Q对象和棘手的逻辑

时间:2015-11-02 14:45:40

标签: python django performance django-queryset django-q

我在Django开发了一个基于网络的聊天应用程序。人们可以在其中形成自己的聊天组,邀请其他人并在所述组中聊天。

我想隔离最近在线的所有用户并且:(i)已经为特定群组发送了邀请 ,或者(ii)已经参与(即已回复< / strong>)至少一次在同一个给定的组中。请注意,user是一个香草django.contrib.auth user

要做到这一点,我写信:

online_invited_replied_users = User.objects.filter(id__in=recently_online,(Q()|Q()))

假设recently_online被正确制定。两个 Q对象应该是什么?

第一个Q()应该引用invitees,第二个引用至少回复一次的用户。我似乎在编写一个全面,高效的数据库查询时遇到了代码编写者的问题。请指教!

相关模型是:

class Group(models.Model):
    topic = models.TextField(validators=[MaxLengthValidator(200)])
    owner = models.ForeignKey(User)
    created_at = models.DateTimeField(auto_now_add=True)

class GroupInvite(models.Model):
    #this is a group invite object
    invitee = models.ForeignKey(User, related_name='invitee')
    inviter = models.ForeignKey(User, related_name ='inviter')
    sent_at = models.DateTimeField(auto_now_add=True)
    which_group = models.ForeignKey(Group)

class Reply(models.Model):
    #if a user has replied in a group, count that as participation
    text = models.TextField(validators=[MaxLengthValidator(500)])
    which_group = models.ForeignKey(Group)
    writer = models.ForeignKey(User)
    submitted_on = models.DateTimeField(auto_now_add=True)

注意:随时可以询问更多信息;我意识到我可能遗漏了一些东西。

1 个答案:

答案 0 :(得分:2)

对于已被邀请加入群组group的用户,请向后关注GroupInvite.invitee外键。

already_invited = Q(invitee__which_group=group)

您选择的相关名称invitee并不真正有意义,因为它链接到群组邀请,而不是用户。也许`group_invites_received&#39;会更好。

对于已经回复的用户,请向后按Reply.writer外键。

already_replied = Q(reply__which_group=group)

在这种情况下,它是reply。因为您还没有指定相关名称。

请注意您当前的伪代码

User.objects.filter(id__in=recently_online,(Q()|Q()))

在关键字arg&#39;。

之后会出现错误&#39;非关键字arg

您可以通过在关键字参数

之前移动非关键字参数来解决此问题
User.objects.filter((Q()|Q()), id__in=recently_online)

或将它们放在单独的过滤器中:

User.objects.filter(id__in=recently_online).filter(Q()|Q())

最后请注意,您可能需要在查询集上使用distinct(),否则用户可能会出现两次。