【问题标题】:Django: how to make an "order by" filter based on a foreign keyDjango:如何根据外键制作“order by”过滤器
【发布时间】:2016-05-18 17:33:12
【问题描述】:

我有一个Conversation 模型和一个Message 模型。 Message 有一个日期字段 date_creation

Conversation 有多个 Messagemessages,如下所示:

class Message(models.Model):
    date_last_modif = models.DateTimeField(auto_now=True)
    src = models.ForeignKey('User', related_name='message_src')
    dst = models.ForeignKey('User', related_name='message_dst')
    is_read = models.BooleanField(default=False)
    message = models.TextField(null=True, blank=True)

class Conversation(models.Model):
    messages = models.ManyToManyField(Message, related_name='conversations')

我想做的是获取所有没有已读消息的对话,按最近的消息排序。

所以这是我的第一个过滤器,它获取所有尚未阅读消息的对话:

p = current_user  # code omitted for sake of clarity
convs_not_read = Conversation.objects.filter(
    Q(messages__dst=p, messages__is_read=False)).distinct()

请注意,我需要 distinct 才能仅获取会话 ID 一次,否则,如果有多个未读消息,您将获得与未读消息一样多的相同 ID阅读此对话中的消息。

从现在开始,我试图让所有没有“没有”未读消息的对话,并按最近的消息排序。

我已经开始了:

convs_read = Conversation.objects
        .filter(messages__dst=p)
        .exclude(pk__in=convs_not_read.values_list('id', flat=True))
        .distinct()

这可行,但它们没有被最新消息过滤。我被困在这里。你会怎么做?

如果我尝试:在此查询中的任何位置添加.order_by('-messages__date_last_modif'),它没有任何效果,这里:

        .filter(messages__dst=p)
        .order_by('-messages__date_last_modif')
        .exclude(pk__in=convs_not_read.values_list('id', flat=True))
        .distinct()

...或这里:

        .filter(messages__dst=p)
        .exclude(pk__in=convs_not_read.values_list('id', flat=True))
        .distinct()
        .order_by('-messages__date_last_modif')

...不会改变结果

【问题讨论】:

  • 你试过convs_read = convs_read.order_by('-messages__date_last_modif')吗?
  • 是的,我会更新我的问题

标签: python django


【解决方案1】:

尝试使用:

my_query.order_by('-conversations__date_last_modif')

因为您使用related_name 作为"conversations"

【讨论】:

    【解决方案2】:

    我正在手动进行此“排序”:我首先按消息日期排序,然后对于每条消息,如果尚未添加其对话的 pk,我会添加它。我很确定这不是最优化的解决方案,所以如果你有任何基于这个 - 工作 - 解决方案的建议,我是你的人!

    l = []
    for m in Message.objects.filter(dst=p).order_by('-date_last_modif'):
        for c in m.conversations.all():
            if c not in l:
                l.append(c.pk)
    conversations_read = [c for c in Conversation.objects.filter(pk__in=l)]
    

    【讨论】:

    • 对不起,我希望我有时间,但现在我没有时间
    猜你喜欢
    • 2019-07-23
    • 2020-12-30
    • 1970-01-01
    • 2020-12-25
    • 2015-04-13
    • 1970-01-01
    • 2016-06-10
    • 1970-01-01
    • 2018-03-19
    相关资源
    最近更新 更多