Что такое «экземпляр», передаваемый в функцию to_representation моего ListSerializer? - PullRequest
1 голос
/ 31 марта 2020

Цель этого проекта - создать API, который обновляется ежечасно с самыми последними коэффициентами ставок для списка игр, которые я буду ежечасно извлекать из inte rnet. Структура цели для возвращенного JSON будет представлять каждую игру в качестве родительского объекта, а вложенные дочерние элементы будут первыми 1 записями для каждого из создателей строк, очищенных по обновленной дате. Насколько я понимаю, лучший способ выполнить sh - это изменить функцию to_representation в ListSerializer, чтобы она возвращала соответствующий набор запросов.

Поскольку мне нужен 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

Теперь, если я удалю эти исключения исключения, я получу индекс списка вне диапазона. Первоначально я думал, что есть что-то еще, что зависит от «данных», возвращаемых в виде списка, поэтому я создал фрагмент понимания списка, но это не решает проблему.

Итак, мой вопрос 1) Есть ли более простой способ сделать то, к чему я иду? Я не использую postgres бэкэнд, так что отдельный для меня недоступен. и 2) если нет, мне не ясно, какой экземпляр передается или что ожидается вернуть. Я ознакомился с документацией, и похоже, что он ожидает словарь, и это может быть частью проблемы, но опять же сообщение об ошибке ссылается на список. https://www.django-rest-framework.org/api-guide/serializers/#overriding -сериализация-и-десериализация-поведение

Я ценю любую помощь в понимании того, что здесь происходит заранее.

Редактировать: Остальные сериализаторы :

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  

Спасибо

1 Ответ

1 голос
/ 31 марта 2020

Чтобы ответить на вопрос в заголовке:

instance, передаваемый Serializer.to_representation(), - это экземпляр, который вы передаете при инициализации сериализатора

queryset = MyModel.objects.all()
Serializer(queryset, many=True)

instance = MyModel.objects.all().first()
Serializer(data)

Обычно вы не должно наследоваться от ListSerializer как такового. Вы можете наследовать от BaseSerializer и всякий раз, когда вы передаете many=True во время инициализации, он автоматически «становится a ListSerializer`. Вы можете увидеть это в действии здесь

Чтобы ответить на вашу проблему

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)
...