在Django中进行替换

时间:2017-02-13 09:24:23

标签: mysql django orm

我有一个实现小型聊天应用程序的Django 1.9项目。来自特定收件人的所有邮件都被分组到对话框中,因此模型定义如下:

class Dialog(models.Model):
    # Some fields

class Message(models.Model):
    dialog = models.ForeignKey(Dialog, ...) 
    text = models.TextField()
    is_read = models.BooleanField(default = False)

我的目标是使用呈现对话框的表格呈现模板。对于表格中的每个对话框,我需要看到

  1. 未读邮件的数量
  2. 最后一条消息的文字
  3. 为了说明,请考虑下面的模拟数据:

    输入:

    id      dialog_id    message          is_read
    1          1         Hello, sir        false
    2          1         My name is        true
    3          1         Jack              true
    4          2         This site         false
    5          2         is perfect        false
    6          2         Cheers            false
    

    期望的输出:

    dialog_id     last_message_in_dialog      unread_messages_count
        1                  Jack                         1 
        2                 Cheers                        3
    

    在纯mysql中,我会写一个这样的查询:

    select 
           a.dialog_id, 
           text as last_message_in_dialog,
           (select count(*) from message 
            where dialog_id = a.dialog_id and is_read = false) as unread_messages_count
    from message a
    where id in (select max(id) from message group by dialog_id)
    

    在Django术语中,我有以下代码:

    max_id_qs = Message.objects.\
                        values('dialog__id').\
                        annotate(max_id = Max('id'),).values('max_id')
    
    qs = Message.objects.filter(id__in = max_id_qs).\
                         values('dialog__id', 'text')
    

    此代码非常适合在每个对话框中获取最后一条消息。但问题是我无法弄清楚如何在Django中实现子查询(select count(*) from message where dialog_id = a.dialog_id and is_read = false)。也许我对max_id_qs的总体方法是错误的,并且在Django ORM中实现查询有更优雅和清晰的方法? 我花了一整天时间试图解决这个问题。请帮帮我!

1 个答案:

答案 0 :(得分:0)

这将有效: -

allDistinctIdWithNotReadMsg = 
   Message.objects.filter(is_read=False).values('id').annotate(the_count=Count('is_read',distinct('id')))

for ids in allDistinctIdWithNotReadMsg:
    lastMsg = Message.objects.filter(dialog_id=ids['id']).order_by("-id")[0]
    for msg in lastMsg:

        print ids['id'] ,msg.message,ids['the_count']