传递给 ListSerializer 的 to_representation 函数的 "instance" 是什么?
What is the "instance" being passed to the to_representation function of my ListSerializer?
这个项目的目标是创建一个 API 每小时刷新一次的游戏列表的最新投注赔率,我将每小时从互联网上收集这些游戏。 JSON returned 的目标结构将每个游戏作为父对象,嵌套的子对象将是每个 linemakers 在更新日期前被抓取的前 1 条记录。我的理解是,实现此目的的最佳方法是将 ListSerializer 中的 to_representation 函数修改为 return 适当的查询集。
因为我需要父元素的 game_id 来获取相应游戏的子元素,所以我试图从传递的数据中提取 game_id。问题是当我通过异常看到它包含的内容时,该行看起来被正确填充,但是当我让完整代码 运行 时,我得到一个列表索引超出范围异常。
例如
class OddsMakerListSerializer(serializers.ListSerializer):
def to_representation(self, data):
game = data.all()[0].game_id
#if I put this here it evaluates to 1 which should run the raw sql below correctly
raise Exception(game)
data = OddsMaker.objects.filter(odds_id__in = RawSQL(''' SELECT o.odds_id
FROM gamesbackend_oddsmaker o
INNER JOIN (
SELECT game_id
, oddsmaker
, max(updated_datetime) as last_updated
FROM gamesbackend_oddsmaker
WHERE game_id = %s
GROUP BY game_id
, oddsmaker
) l on o.game_id = l.game_id
and o.oddsmaker = l.oddsmaker
and o.updated_datetime = l.last_updated
''', [game]))
#if I put this here the data appears to be populated correctly and contain the right data
raise Exception(data)
data = [game for game in data]
return data
现在,如果我删除这些引发的异常,我会得到列表索引超出范围。我最初的想法是,还有其他一些东西依赖于 "data" 被 returned 作为列表,所以我创建了列表理解片段,但这并没有解决问题。
所以,我的问题是 1) 是否有更简单的方法来完成我的目标?我没有使用 postgres 后端,所以 distinct on 对我不可用。和 2) 如果不是,我不清楚传入的实例是什么,或者预期 returned 是什么。我查阅了文档,它看起来好像需要一本字典,这可能是问题的一部分,但错误消息再次引用了一个列表。 https://www.django-rest-framework.org/api-guide/serializers/#overriding-serialization-and-deserialization-behavior
感谢任何帮助我提前了解这里发生的事情的人。
编辑:
其余的序列化程序:
class OddsMakerSerializer(serializers.ModelSerializer):
class Meta:
list_serializer_class = OddsMakerListSerializer
model = OddsMaker
fields = ('odds_id','game_id','oddsmaker','home_ml',
'away_ml','home_spread','home_spread_odds',
'away_spread_odds','total','total_over_odds',
'total_under_odds','updated_datetime')
class GameSerializer(serializers.ModelSerializer):
oddsmaker_set = OddsMakerSerializer(many=True, read_only=True)
class Meta:
model = Game
fields = ('game_id','date','sport', 'home_team',
'away_team','home_score', 'away_score',
'home_win','away_win', 'game_completed',
'oddsmaker_set')
models.py:
class Game(models.Model):
game_id = models.AutoField(primary_key=True)
date = models.DateTimeField(null=True)
sport=models.CharField(max_length=256, null=True)
home_team = models.CharField(max_length=256, null=True)
away_team = models.CharField(max_length=256, null=True)
home_score = models.IntegerField(default=0, null=True)
away_score = models.IntegerField(default=0, null=True)
home_win = models.BooleanField(default=0, null=True)
away_win = models.BooleanField(default=0, null=True)
game_completed = models.BooleanField(default=0, null=True)
class OddsMaker(models.Model):
odds_id = models.AutoField(primary_key=True)
game = models.ForeignKey('Game', on_delete = models.CASCADE)
oddsmaker = models.CharField(max_length=256)
home_ml = models.IntegerField(default=999999)
away_ml = models.IntegerField(default=999999)
home_spread = models.FloatField(default=999)
home_spread_odds = models.IntegerField(default=9999)
away_spread_odds = models.IntegerField(default=9999)
total = models.FloatField(default=999)
total_over_odds = models.IntegerField(default=999)
total_under_odds = models.IntegerField(default=999)
updated_datetime = models.DateTimeField(auto_now=True)
views.py:
class GameView(viewsets.ModelViewSet):
queryset = Game.objects.all()
serializer_class = GameSerializer
谢谢
回答标题中的问题:
传递给Serializer.to_representation()
的instance
就是你在初始化序列化器时传递的实例
queryset = MyModel.objects.all()
Serializer(queryset, many=True)
instance = MyModel.objects.all().first()
Serializer(data)
通常您不必继承 ListSerializer
本身。您可以从 BaseSerializer
继承,每当您在初始化期间传递 many=True
时,它将自动“成为 a
ListSerializer”。 You can see this in action here
回答你的问题
from django.db.models import Max
class OddsMakerListSerializer(serializers.ListSerializer):
def to_representation(self, data): # data passed is a queryset of oddsmaker
# Do your filtering here
latest_date = data.aggregate(
latest_date=Max('updated_datetime')
).get('latest_date').date()
latest_records = data.filter(
updated_date_time__year=latest_date.year,
updated_date_time__month=latest_date.month,
updated_date_time__day=latest_date.day
)
return super().to_representation(latest_records)
这个项目的目标是创建一个 API 每小时刷新一次的游戏列表的最新投注赔率,我将每小时从互联网上收集这些游戏。 JSON returned 的目标结构将每个游戏作为父对象,嵌套的子对象将是每个 linemakers 在更新日期前被抓取的前 1 条记录。我的理解是,实现此目的的最佳方法是将 ListSerializer 中的 to_representation 函数修改为 return 适当的查询集。
因为我需要父元素的 game_id 来获取相应游戏的子元素,所以我试图从传递的数据中提取 game_id。问题是当我通过异常看到它包含的内容时,该行看起来被正确填充,但是当我让完整代码 运行 时,我得到一个列表索引超出范围异常。
例如
class OddsMakerListSerializer(serializers.ListSerializer):
def to_representation(self, data):
game = data.all()[0].game_id
#if I put this here it evaluates to 1 which should run the raw sql below correctly
raise Exception(game)
data = OddsMaker.objects.filter(odds_id__in = RawSQL(''' SELECT o.odds_id
FROM gamesbackend_oddsmaker o
INNER JOIN (
SELECT game_id
, oddsmaker
, max(updated_datetime) as last_updated
FROM gamesbackend_oddsmaker
WHERE game_id = %s
GROUP BY game_id
, oddsmaker
) l on o.game_id = l.game_id
and o.oddsmaker = l.oddsmaker
and o.updated_datetime = l.last_updated
''', [game]))
#if I put this here the data appears to be populated correctly and contain the right data
raise Exception(data)
data = [game for game in data]
return data
现在,如果我删除这些引发的异常,我会得到列表索引超出范围。我最初的想法是,还有其他一些东西依赖于 "data" 被 returned 作为列表,所以我创建了列表理解片段,但这并没有解决问题。
所以,我的问题是 1) 是否有更简单的方法来完成我的目标?我没有使用 postgres 后端,所以 distinct on 对我不可用。和 2) 如果不是,我不清楚传入的实例是什么,或者预期 returned 是什么。我查阅了文档,它看起来好像需要一本字典,这可能是问题的一部分,但错误消息再次引用了一个列表。 https://www.django-rest-framework.org/api-guide/serializers/#overriding-serialization-and-deserialization-behavior
感谢任何帮助我提前了解这里发生的事情的人。
编辑: 其余的序列化程序:
class OddsMakerSerializer(serializers.ModelSerializer):
class Meta:
list_serializer_class = OddsMakerListSerializer
model = OddsMaker
fields = ('odds_id','game_id','oddsmaker','home_ml',
'away_ml','home_spread','home_spread_odds',
'away_spread_odds','total','total_over_odds',
'total_under_odds','updated_datetime')
class GameSerializer(serializers.ModelSerializer):
oddsmaker_set = OddsMakerSerializer(many=True, read_only=True)
class Meta:
model = Game
fields = ('game_id','date','sport', 'home_team',
'away_team','home_score', 'away_score',
'home_win','away_win', 'game_completed',
'oddsmaker_set')
models.py:
class Game(models.Model):
game_id = models.AutoField(primary_key=True)
date = models.DateTimeField(null=True)
sport=models.CharField(max_length=256, null=True)
home_team = models.CharField(max_length=256, null=True)
away_team = models.CharField(max_length=256, null=True)
home_score = models.IntegerField(default=0, null=True)
away_score = models.IntegerField(default=0, null=True)
home_win = models.BooleanField(default=0, null=True)
away_win = models.BooleanField(default=0, null=True)
game_completed = models.BooleanField(default=0, null=True)
class OddsMaker(models.Model):
odds_id = models.AutoField(primary_key=True)
game = models.ForeignKey('Game', on_delete = models.CASCADE)
oddsmaker = models.CharField(max_length=256)
home_ml = models.IntegerField(default=999999)
away_ml = models.IntegerField(default=999999)
home_spread = models.FloatField(default=999)
home_spread_odds = models.IntegerField(default=9999)
away_spread_odds = models.IntegerField(default=9999)
total = models.FloatField(default=999)
total_over_odds = models.IntegerField(default=999)
total_under_odds = models.IntegerField(default=999)
updated_datetime = models.DateTimeField(auto_now=True)
views.py:
class GameView(viewsets.ModelViewSet):
queryset = Game.objects.all()
serializer_class = GameSerializer
谢谢
回答标题中的问题:
传递给Serializer.to_representation()
的instance
就是你在初始化序列化器时传递的实例
queryset = MyModel.objects.all()
Serializer(queryset, many=True)
instance = MyModel.objects.all().first()
Serializer(data)
通常您不必继承 ListSerializer
本身。您可以从 BaseSerializer
继承,每当您在初始化期间传递 many=True
时,它将自动“成为 a
ListSerializer”。 You can see this in action here
回答你的问题
from django.db.models import Max
class OddsMakerListSerializer(serializers.ListSerializer):
def to_representation(self, data): # data passed is a queryset of oddsmaker
# Do your filtering here
latest_date = data.aggregate(
latest_date=Max('updated_datetime')
).get('latest_date').date()
latest_records = data.filter(
updated_date_time__year=latest_date.year,
updated_date_time__month=latest_date.month,
updated_date_time__day=latest_date.day
)
return super().to_representation(latest_records)