Django:按两列分组且不同,不考虑顺序

问题描述 投票:0回答:1

我有一个

TextMessage
模型,如您所见:

class TextMessaage(models.Model):

    id = models.UUIDField(
        _("Id"),
        primary_key=True,
        default=uuid.uuid4,
        editable=False,
        null=False,
        blank=False,
    )

    created_at = models.DateTimeField(_("Created at"), auto_now_add=True)
    modified_at = models.DateTimeField(_("Modified at"), auto_now=True)

    sender = models.ForeignKey(
        User,
        on_delete=models.PROTECT,
        related_name="sent_messages",
        blank=False,
        null=False,
        verbose_name=_("Sender"),
    )

    receiver = models.ForeignKey(
        User,
        on_delete=models.PROTECT,
        related_name="received_messages",
        blank=False,
        null=False,
        verbose_name=_("Receiver"),
    )

    body = models.TextField(
        null=False,
        blank=False,
        validators=[MaxLengthValidator(4096)],
        verbose_name=_("Body"),
    )

我想做的是获取用户参与的每个对话的最后一条消息。我试过这个:

conversations = (
            models.TextMessage.objects.filter(Q(sender=user) | Q(receiver=user))
            .order_by(
                "sender__id",
                "receiver_id",
                "-modified_at",
            )
            .distinct("sender__id", "receiver_id")
        ).all()

问题是我编写的查询将考虑与 (sender=B,receiver=A) 不同的对 (sender=A,receiver=B),这不是我正在寻找的。我希望这两对假设相同,因为无论它们的顺序如何,它们都共享相同的外键。简而言之,我只想要用户参与的每个对话中的最后一条消息,以便我可以显示为列表(如 Whatsapp 聊天列表)。我该怎么办?

为了添加更多信息,我顺便使用 Postgres。

django django-models django-orm
1个回答
0
投票

您可以像这样使用@property(模型属性)来实现这些事情

class TextMessaage(models.Model):

    id = models.UUIDField(
        _("Id"),
        primary_key=True,
        default=uuid.uuid4,
        editable=False,
        null=False,
        blank=False,
    )

    created_at = models.DateTimeField(_("Created at"), auto_now_add=True)
    modified_at = models.DateTimeField(_("Modified at"), auto_now=True)

    sender = models.ForeignKey(
        User,
        on_delete=models.PROTECT,
        related_name="sent_messages",
        blank=False,
        null=False,
        verbose_name=_("Sender"),
    )

    receiver = models.ForeignKey(
        User,
        on_delete=models.PROTECT,
        related_name="received_messages",
        blank=False,
        null=False,
        verbose_name=_("Receiver"),
    )

    body = models.TextField(
        null=False,
        blank=False,
        validators=[MaxLengthValidator(4096)],
        verbose_name=_("Body"),
    )

    @property 
    def last_msg(self):
        last_m = TextMessaage.objects.filter(receiver=self.receiver).order_by('-created_at').first()
        return last_m
    


all_msg = TextMessaage.objects.all() # get all conversations 
for m in all_msg:
    print(m.sender.username)
    print(m.receiver.username)
    print(m.body)
    print(m.created_at)
    print(m.last_m) # This will print the last message sent to the user
    print("************")
© www.soinside.com 2019 - 2024. All rights reserved.