Я думаю, что лучшее, что вы можете сделать, это сначала получить идентификатор последнего PlayerStatsHistory
каждого игрока (используя group_by):
latest_stats_history_pks = PlayerStatsHistory.objects.values('player').annotate(max_id=models.Max('id')).values_list('max_id', flat=True)
(у него есть проблема, он использует всех игроковесли вы используете разбиение на страницы, вам не нужны все из них, в этом случае предварительная выборка без фильтрации набора запросов должна быть в порядке)
, тогда только предварительную выборку этих значений следует выполнять в вашем Player
наборе запросов, поэтому:
queryset = Player.objects.all().prefetch_related(models.Prefetch(
'playerstatshistory_set',
queryset=PlayerStatsHistory.objects.filter(pk__in=latest_stats_history_pks), to_attr='last_stat_list'))
поэтому, наконец, ваш get_queryset
метод в вашем представлении должен выглядеть следующим образом:
def get_queryset(self):
latest_stats_history_pks = PlayerStatsHistory.objects.values('player').annotate(max_id=models.Max('id')).values_list('max_id', flat=True)
queryset = Player.objects.all().prefetch_related(models.Prefetch(
'playerstatshistory_set',
queryset=PlayerStatsHistory.objects.filter(pk__in=latest_stats_history_pks), to_attr='last_stat_list'))
return queryset
, и если вы используете FBV, сделайте что-то вроде этого:
from rest_framework.decorators import api_view
from rest_framework.response import Response
@api_view(['GET'])
def player_list(request, format=None):
if request.method == 'GET':
latest_stats_history_pks = PlayerStatsHistory.objects.values('player').annotate(max_id=models.Max('id')).values_list('max_id', flat=True)
players = Player.objects.all().prefetch_related(models.Prefetch(
'playerstatshistory_set',
queryset=PlayerStatsHistory.objects.filter(pk__in=latest_stats_history_pks), to_attr='last_stat_list'))
serializer = PlayerSerializer(players, many=True)
return Response(serializer.data)
также в вашем сериализаторе, измените это поле, как показано ниже:
class PlayerSerializer(HyperlinkedModelSerializer):
details = SerializerMethodField()
def get_details(self, obj):
return {} if not obj.last_stat_list else PlayerStatsSerializer(obj.last_stat_list[-1]).data
class Meta:
model = Player
fields = ('name', 'details')