SerializerMethodField您可以使用ChatSerializer如下:
messages = serializers.SerializerMethodField()
def get_messages(self, chat):
qs = Message.objects.filter(chat=chat).order_by('-date')[:50]
return MessageSerializer(instance=qs, many=True).data
这会为每个实例运行一个单独的查询Chat,但它只获取所需的行数。您必须根据需要自定义字段名称 ( chat, date)。
替代语法@spiritsree 针对相同 SQL 中的结果,使用隐式过滤而不是显式过滤:
qs = chat.messages.order_by('-date')[:50]
需要避免的一件事是在返回列表prefetch_related('messages')的querysetof the中使用,因为预取根本不会被使用,并且会从数据库中提取所有消息,而只会在未使用的情况下被丢弃。ViewSetChat
在另一个答案中因为慢而被驳回的子查询替代方案实际上很有趣。它为您节省了与聊天次数一样多的数据库往返次数。然而,作为交换,数据库必须在内部执行两倍的查询。
多余的查询非常轻量级(通过 id 选择少量消息并对其进行排序),保存的往返可能很容易弥补它们。在我的快速测试中,这种方法比使用SerializerMethodField. 它可能在某种程度上取决于数据;自己测试一下:
from rest_framework import viewsets
from django.db.models import Prefetch, Subquery, OuterRef
class ChatViewSet(viewsets.ModelViewSet):
prefetch = Prefetch(
'messages',
queryset=Message.objects
.filter(id__in=Subquery(Message.objects
.filter(chat=OuterRef('chat_id'))
.order_by('-date')
.values_list('id', flat=True)[:4]))
.order_by('-date')
)
queryset = Chat.objects.prefetch_related(prefetch)