按嵌套对象日期排序
Order by nested objects date
我正在构建一个聊天应用程序,有以下模型代表聊天室、聊天消息和未读消息计数器
class ChatRoom(BaseModel):
name = models.CharField(max_length=255, default='', blank=True)
participants = models.ManyToManyField('accounts.User', related_name='chat_rooms')
class ChatMessage(BaseModel):
text = models.TextField(default='', blank=True)
owner = models.ForeignKey('accounts.User', on_delete=models.CASCADE)
room = models.ForeignKey(ChatRoom, on_delete=models.CASCADE, related_name='messages')
class ChatRoomUnreadMessagesCounter(BaseModel):
room = models.ForeignKey(ChatRoom, on_delete=models.CASCADE, related_name='unread_counters')
owner = models.ForeignKey('accounts.User', on_delete=models.CASCADE)
messages_count = models.IntegerField(default=0)
class BaseModel(models.Model):
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
is_deleted = models.BooleanField(default=False)
class Meta:
abstract = True
我想制作一个 API 视图,该视图将 return 按以下方式排序的 ChatRoom
个对象的列表:ChatRoom
个未读对象按消息计数排序的消息 -> ChatRoom
个按最新消息排序的对象 created_at
后进先出 -> ChatRoom
个按字母顺序排序的对象。我将如何正确构建我的查询集?
这是预期的结果输出
| Room Name | Unread Messages | Last Message |
| Rean | 2 | 09.11.2021T12:00:00 |
| Ash | 1 | 09.11.2021T12:00:24 |
| Altina | 0 | 09.11.2021T12:15:00 |
| Juna | 0 | 09.11.2021T12:14:00 |
| Kurt | 0 | 09.11.2021T12:13:00 |
| Musse | 0 | 09.11.2021T12:12:00 |
| Sharon | 0 | No messages yet |
这可不简单。希望有人得到一个更简单的答案。我的包括 SubQuery.
from django.db.models import OuterRef, Subquery
# get query which references an 'id' field of the parent qs
latest_message_subq = Subquery(Message.objects.filter(
room=OuterRef("id")).order_by("-created_at").values('created_at')[:1]
)
# annotate the unread count per room
# assumes there's only a single counter per owner
unread_count_subq = Subquery(ChatRoomUnreadMessagesCounter.objects.filter(
room=OuterRef("id"), owner=user).values('messages_count')[:1]
)
# Room.objects.all() is the parent qs
# So the OuterRef("id") is pointing to a room id
rooms = Room.objects.annotate(
latest_message_time=latest_message_subq,
unread_count= unread_count_subq
)
# every object in the rooms qs should now have the attributes latest_message_time and unread_count; you can loop it to verify
rooms = rooms.order_by('-unread_count', '-latest_message', 'name')
编辑:更改为在最后获得房间 qs
我正在构建一个聊天应用程序,有以下模型代表聊天室、聊天消息和未读消息计数器
class ChatRoom(BaseModel):
name = models.CharField(max_length=255, default='', blank=True)
participants = models.ManyToManyField('accounts.User', related_name='chat_rooms')
class ChatMessage(BaseModel):
text = models.TextField(default='', blank=True)
owner = models.ForeignKey('accounts.User', on_delete=models.CASCADE)
room = models.ForeignKey(ChatRoom, on_delete=models.CASCADE, related_name='messages')
class ChatRoomUnreadMessagesCounter(BaseModel):
room = models.ForeignKey(ChatRoom, on_delete=models.CASCADE, related_name='unread_counters')
owner = models.ForeignKey('accounts.User', on_delete=models.CASCADE)
messages_count = models.IntegerField(default=0)
class BaseModel(models.Model):
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
is_deleted = models.BooleanField(default=False)
class Meta:
abstract = True
我想制作一个 API 视图,该视图将 return 按以下方式排序的 ChatRoom
个对象的列表:ChatRoom
个未读对象按消息计数排序的消息 -> ChatRoom
个按最新消息排序的对象 created_at
后进先出 -> ChatRoom
个按字母顺序排序的对象。我将如何正确构建我的查询集?
这是预期的结果输出
| Room Name | Unread Messages | Last Message |
| Rean | 2 | 09.11.2021T12:00:00 |
| Ash | 1 | 09.11.2021T12:00:24 |
| Altina | 0 | 09.11.2021T12:15:00 |
| Juna | 0 | 09.11.2021T12:14:00 |
| Kurt | 0 | 09.11.2021T12:13:00 |
| Musse | 0 | 09.11.2021T12:12:00 |
| Sharon | 0 | No messages yet |
这可不简单。希望有人得到一个更简单的答案。我的包括 SubQuery.
from django.db.models import OuterRef, Subquery
# get query which references an 'id' field of the parent qs
latest_message_subq = Subquery(Message.objects.filter(
room=OuterRef("id")).order_by("-created_at").values('created_at')[:1]
)
# annotate the unread count per room
# assumes there's only a single counter per owner
unread_count_subq = Subquery(ChatRoomUnreadMessagesCounter.objects.filter(
room=OuterRef("id"), owner=user).values('messages_count')[:1]
)
# Room.objects.all() is the parent qs
# So the OuterRef("id") is pointing to a room id
rooms = Room.objects.annotate(
latest_message_time=latest_message_subq,
unread_count= unread_count_subq
)
# every object in the rooms qs should now have the attributes latest_message_time and unread_count; you can loop it to verify
rooms = rooms.order_by('-unread_count', '-latest_message', 'name')
编辑:更改为在最后获得房间 qs