Django / DRF - prefetch_related (), возвращающий все объекты без надлежащего сопоставления отношения внешнего ключа? - PullRequest
0 голосов
/ 21 сентября 2019

Итак, ребята, у меня возникла проблема с моими конечными точками.Я пытался использовать return Player.objects.prefetch_related('playerstatistic_set'), чтобы вернуть мне объекты Player, которые соответствуют объектам в модели PlayerStatistic.Таблица PlayerStatistic в настоящее время имеет только одну строку, поэтому player_id = 1 должна быть единственной возвращаемой, но в настоящее время prefetch_related () возвращает ВСЕ объекты Player.

Я попытался войти в модель PlayerStatistic и добавить related_nameпримерно так - player = models.ForeignKey(Player, on_delete=models.CASCADE, related_name='player_stats') и изменение предварительной выборки на prefetch_related('player_stats'), но это все равно просто возвращает все объекты Player.

Модели -


class Player(models.Model):
    # class for Player model
    name = models.CharField(max_length=100)
    team = models.ForeignKey(Team, on_delete=models.CASCADE)


class Game(models.Model):
    # class for Game model

    home_team = models.ForeignKey(Team, related_name='home_games',
                                     on_delete=models.CASCADE)
    away_team = models.ForeignKey(Team, related_name='away_games',
                                     on_delete=models.CASCADE)
    date = models.DateField()


class PlayerStatistic(models.Model):
    # class for individual player statistics

    game = models.ForeignKey(Game, on_delete=models.CASCADE)
    player = models.ForeignKey(Player, on_delete=models.CASCADE)
    team = models.ForeignKey(Team, on_delete=models.CASCADE)
    points = models.IntegerField()
    assists = models.IntegerField()
    rebounds = models.IntegerField()

Моя функция get_queryset в моем представлении проигрывателя-

class PlayerViewSet(viewsets.ModelViewSet):
    # ViewSet to display Players

    queryset = Player.objects.all()
    serializer_class = PlayerSerializer

    def get_queryset(self):
        return queryset.prefetch_related('playerstatistic_set')

Конечно, в моем Сериализаторе проигрывателя я тоже пытался вложить в него PlayerStatistic Serializer, но результат, кажется, одинаков, независимо от того, есть у меня вложенный сериализатор или нет.

{id: 1, game_id: 1, player_id: 1, team_id: 1, points: 20, assists: 10, rebounds: 2}

Эта строка является единственной строкой в ​​PlayerStatistic, поэтому должен быть возвращен объект Player с player_id = 1, но возвращены все строки (12 строк).

EDIT - Сериализаторы ниже -


class PlayerStatisticSerializer(serializers.ModelSerializer):
    # Serializer for player statistics object

    class Meta:
        model = PlayerStatistic
        fields = '__all__'


class PlayerSerializer(serializers.ModelSerializer):
    # Serializer for Player objects
    playerstatistic = PlayerStatisticSerializer(many=True, read_only=True)

    class Meta:
        model = Player
        fields = '__all__'

1 Ответ

1 голос
/ 22 сентября 2019

Вы можете запутаться в функции prefetch_related, в вашем примере все работает, как ожидалось.Player.objects.all() возвращает все объекты Player, и queryset.prefetch_related('playerstatistic_set') не изменяет результаты запроса, а только предварительно выбирает связанные объекты в качестве оптимизатора запросов.

Если вы хотите запрашивать только игроков, у которых есть статистика игрока 'Придется работать наоборот, то есть, выбрав статистику игрока и используя Player в качестве вложенного сериализатора в PlayerStatisticSerializer.


Другим быстрым способом достижения того, что вы хотите с помощью вашей кодовой базы, будет удаление всех пользователей.без playerstatistic_set с .filter методом

def get_queryset(self):
    return queryset.prefetch_related('playerstatistic_set').filter(playerstatistic_set__isnull=False)
...