Упорядочение по дате вложенных объектов
Я создаю приложение для чата и имею следующие модели, представляющие чат, сообщение чата и счетчик непрочитанных сообщений
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, которое возвращало бы список 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')
EDIT: Изменено, чтобы получить Room qs в конце