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

Complex Django queryset filtering, involving Q objects and tricky logic

我有一个用 Django 开发的基于网络的聊天应用程序。人们可以在里面组建自己的聊天群,邀请其他人在群里聊天。

我想隔离所有最近在线的用户并且:(i) 已经收到给定群组的邀请,或者 (ii) 已经参与(即在同一给定组中至少回复了一次。请注意 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)

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

对于已经受邀加入组 group 的用户,请向后跟随 GroupInvite.invitee 外键。

already_invited = Q(invitee__which_group=group)

您选择的 related_name invitee 没有任何意义,因为它链接到群组邀请,而不是用户。也许 `group_invites_received' 会更好。

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

already_replied = Q(reply__which_group=group)

在本例中为 reply。因为您没有指定相关名称。

注意你当前的伪代码

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

会报错'non-keyword arg after keyword arg'.

您可以通过将非关键字参数移到关键字参数之前来解决此问题,

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

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

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

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