gpt4 book ai didi

python - 如何有效地在 REST 序列化程序中找到相关字段的数据库?

转载 作者:行者123 更新时间:2023-11-28 21:35:40 25 4
gpt4 key购买 nike

我的数据库有一个复杂的体系结构,并且在编写相应的 REST API 时遇到了麻烦。

上下文:我每小时都在公共(public) API 上请求各种信息,包括我想要保留历史记录的数据。

这是我正在使用的模型

class Player(models.Model):
name = models.CharField(max_length=255)

class PlayerStatsHistory(models.Model):
player = models.ForeignKey('Player', null=True, on_delete=models.CASCADE)
last_refresh = models.DateTimeField(null=True)
...

这样,我可以存储每个用户的统计信息中的每一个变化。
我为 Player 编写了 2 个序列化程序一个用于 PlayerStatsHistory .最简单的工作正常
class PlayerStatsSerializer(HyperlinkedModelSerializer):
class Meta:
model = PlayerStatsHistory
fields = ('last_refresh', ...)

但是,当我需要请求一位玩家的最新统计数据时,我会感到困惑:
class PlayerSerializer(HyperlinkedModelSerializer):
details = SerializerMethodField()

def get_details(self, obj):
return PlayerStatsSerializer(PlayerStatsHistory.objects.filter(player=obj).order_by('-last_refresh').first()).data

class Meta:
model = Player
fields = ('name', 'details')

这工作正常,但会在提供给 PlayerSerializer 的每个播放器上命中数据库我觉得我做错了。

我该如何改进这个解决方案?

最佳答案

我认为您能做的最好的事情是首先获取最后一个 PlayerStatsHistory 的 id每个玩家的(使用 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')

关于python - 如何有效地在 REST 序列化程序中找到相关字段的数据库?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52029155/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com