Django ORM显示最新的对话消息

时间:2016-09-01 02:47:47

标签: sql django

我正在尝试获取每个组的最新文本

我的模特是:

class SampleMessaging(models.Model):
    receiver_id = models.IntegerField()
    sender_id = models.IntegerField()
    message = models.TextField()
    order = models.IntegerField()

如果我选择SampleGrouping.objects.all():

,这将是输出
--------------------------------------------------------
id | sender_id|receiver_id|    message      | order
--------------------------------------------------------
1  |    1       |       1       | Hello World!  | 1
2  |    1       |       1       | Hello World2! | 2
3  |    2       |       1       | Hello World3! | 1
4  |    2       |       1       | Hello World4! | 2
5  |    1       |       2       | Hello World5! | 3
6  |    1       |       3       | Hi World!     | 1
7  |    1       |       3       | Hi World2!    | 2
8  |    1       |       3       | H i World3!   | 3
9  |    4       |       1       | Hi Hello!     | 1
10 |    4       |       1       | Hi Hello2!    | 2
11 |    4       |       1       | Hi Hello3!    | 3
12 |    5       |       1       | Gintama 1!    | 1
13 |    5       |       1       | Gintama 22!   | 2
14 |    1       |       6       | Sakata 1!     | 1
15 |    1       |       6       | Sakata 32!    | 2
16 |    1       |       5       | Gintama 256!  | 3

我需要的是一个ORM,它将导致:

---------------------------------------------------------------
id | sender_id  |     receiver_id   |    message    | order
---------------------------------------------------------------
5  |    1       |           2       | Hello World5! | 3
8  |    1       |           3       | H i World3!   | 3
11 |    4       |           1       | Hi Hello3!    | 3
16 |    1       |           5       | Gintama 256!  | 3
15 |    1       |           6       | Sakata 32!    | 2

将此模型视为对话表,我想要的是显示每个用户对话的所有最新消息(按顺序确定)

1 个答案:

答案 0 :(得分:2)

我无法想到比首先按数据分组更好的方法

from django.db.models import Max, Q

filter_data = list(SampleMessaging.objects.all().values('sender_id', 'receiver_id').annotate(order=Max('order')).distinct())

而不是将它与多个Q objects组合,以便像这样过滤它们

在评论中修复案例

# http://stackoverflow.com/questions/39267554/filter-list-of-dicts-by-higest-value-of-dict-and-taking-reversed-values-into-acc/39267938#39267938 
result = {}
for item in filter_data:
    key = frozenset([item["sender_id"], item["receiver_id"]])
    if key not in result or result[key]["order"] < item["order"]:
        result[key] = item
qs_data = result.values()

# and now we can prepare our Q
qs_filter = Q(**qs_data[0])
for data in qs_data[1:]:
     qs_filter |= Q(**data)

desired_qs = SampleMessaging.objects.filter(qs_filter)

注意:仅当您可以保证sender_idreceiver_idorder的组合是唯一的时,此功能才有效。

<强>加成 将其包装到custom manager方法中,以便可以像

一样简单地调用它
SampleMessaging.objects.latest_messages()