Django Rest обратные вложенные отношения в сериализаторах
Я работаю над созданием конечной точки только GET, которая показывает турнирную таблицу данного сезона для спортивной лиги. Честно говоря, на данный момент я перепробовал почти все, но безуспешно. Все другие сериализаторы пока работают нормально, и нет никаких проблем с тем, как настроена моя база данных. Я опустил многие поля и таблицы из-за сложности, но все, что имеет отношение к вопросу, включено ниже.
Сначала позвольте мне показать вам примерный формат того, как я хочу вернуть JSON.
Образец ответа (Конечная цель)
{
divisions: [
{
"divisionName": "WEEKNIGHT B",
"divisionId": "ee68d8ab-2752-4df6-b11d-d289573c66df",
teams: [
{
"teamId": "b07560bc-aac2-4c6c-bbfe-11a368137712",
"statsId": "53852698-9b78-4f36-9a2e-4751b21972f9",
"teamName": "FNA",
},
{
"teamId": "406eb5aa-6004-4220-b219-59476a3136d1",
"statsId": "a96ebf10-87c5-4f19-99c3-867253f4a502",
"teamName": "COPENHAGEN ROAD SODAS",
},
]
},
{
"divisionName": "WEEKNIGHT C",
"divisionId": "4e1469ae-2435-4a3d-a621-19a979ede7c1",
teams: [
{
"teamId": "ebc7e632-073e-4484-85f9-29c0997bec25",
"statsId": "cd6373a7-4f53-4286-80f2-eb3a8a49ee3a",
"teamName": "HAWKS",
"gamesPlayed": 29,
},
{
"teamId": "d8cda7a6-15f4-4e8f-8c65-ef14485957e4",
"statsId": "4492a128-763a-44ad-9ffa-abae2c39b425",
"teamName": "DUISLANDERS",
},
]
}
]
}
Через URL я передаю идентификатор сезона, поэтому все основывается на идентификаторе сезона. Ниже приведен пример того, как я могу воспроизвести нужный мне тип ответа, итерируя некоторые запросы, которые, как я знаю, довольно беспорядочны, но я использую их только для примера.
Пример запроса, чтобы показать, как это можно сделать с помощью запросов
standingsDict = {
"standings": []
}
divisionList = []
season = Season.objects.get(name='Fall 2021')
divisions = Division.objects.filter(seasondivision__season__id=season.id)
for div in divisions:
teamstats = TeamStats.objects.filter(
season_division_team__season_division__season_id=season.id,
season_division_team__season_division__division_id=div)
divDict = {
"divisionName": div.name,
"divisionId": div.id,
"teams": []
}
teamsList = []
for stats in teamstats:
teamDict = {
"teamId": stats.season_division_team.team.id,
"statsId": stats.id,
"seasonDivisionTeamId": stats.season_division_team_id,
"teamName": stats.season_division_team.team.name,
}
teamsList.append(teamDict)
divDict['teams'] = teamsList
divisionList.append(divDict)
standingsDict['standings'] = divisionList
Выходной фрагмент этого цикла
{
"standings":[
{
"divisionName":"WEEKNIGHT B",
"divisionId":"UUID(""ee68d8ab-2752-4df6-b11d-d289573c66df"")",
"teams":[
{
"teamId":"UUID(""756ea44f-885f-4ea0-ae4c-8a72c894067f"")",
"statsId":"UUID(""8ef1f683-ad5b-40d8-9277-0c2689cff771"")",
"seasonDivisionTeamId":"UUID(""19e29f9a-af04-4a4f-9e38-bad0cbf8817d"")",
"teamName":"GABAGOOLS"
},
{
"teamId":"UUID(""aefdc0dc-e2aa-4ce5-ad28-47f0724b57ab"")",
"statsId":"UUID(""05e0012c-0adc-4d15-bbc5-901e49489667"")",
"seasonDivisionTeamId":"UUID(""8adab3d1-7614-4ece-92f5-f0ab34b23c4c"")",
"teamName":"LONG BEACH THUNDER MAJOR"
},
В настоящее время с тем, как все настроено, я могу перейти к отношениям FK, чтобы получить их прямым способом, например, я могу перейти от SeasonDivisionTeam, получить TeamStatsSerializer, и для каждой команды я могу отобразить дивизион. Но это отображает один и тот же дивизион несколько раз для всех командных статистик, что не то, что я ищу.
Модели
class BaseModel(LifecycleModelMixin, models.Model):
date_modified = models.DateTimeField(auto_now=True)
date_created = models.DateTimeField(auto_now_add=True)
id = models.UUIDField(default=uuid.uuid4, unique=True, primary_key=True, editable=False)
class Meta:
abstract = True
class Season(BaseModel):
name = models.CharField(max_length=50)
startDate = models.DateField(null=True, blank=True)
endDate = models.DateField(null=True, blank=True)
class Division(BaseModel):
name = models.CharField(max_length=50)
seasons = models.ManyToManyField(Season, through='SeasonDivision')
class SeasonDivision(LifecycleModelMixin, models.Model):
id = models.UUIDField(default=uuid.uuid4, unique=True, primary_key=True, editable=False)
division = models.ForeignKey(Division, on_delete=models.CASCADE)
season = models.ForeignKey(Season, on_delete=models.CASCADE)
class Team(BaseModel):
name = models.CharField(max_length=50)
season_divisions = models.ManyToManyField(SeasonDivision, through='SeasonDivisionTeam')
class SeasonDivisionTeam(LifecycleModelMixin, models.Model):
id = models.UUIDField(default=uuid.uuid4, unique=True, primary_key=True, editable=False)
team = models.ForeignKey(Team, on_delete=models.CASCADE)
season_division = models.ForeignKey(SeasonDivision, on_delete=models.CASCADE)
class Player(BaseModel):
season_division_teams = models.ManyToManyField(SeasonDivisionTeam, through='SeasonDivisionTeamPlayer')
firstName = models.CharField(max_length=80)
class SeasonDivisionTeamPlayer(LifecycleModelMixin, models.Model):
id = models.UUIDField(default=uuid.uuid4, unique=True, primary_key=True, editable=False)
player = models.ForeignKey(Player, on_delete=models.CASCADE)
season_division_team = models.ForeignKey(SeasonDivisionTeam, on_delete=models.CASCADE)
class PlayerStats(BaseModel):
season_division_team_player = models.ForeignKey(SeasonDivisionTeamPlayer, on_delete=models.CASCADE)
goals = models.IntegerField(default=0)
class TeamStats(BaseModel):
season_division_team = models.ForeignKey(SeasonDivisionTeam, on_delete=models.CASCADE)
regWins = models.IntegerField(default=0)
Сериализаторы (Многие из них были изменены несколько раз, поэтому то, что я привожу ниже, - это только последнее, что я тестировал и что не работало. )
class StandingsSerializer(serializers.ModelSerializer):
teamstats = TeamStatsSerializer(many=True, source='teamstats_set')
class Meta:
model = SeasonDivisionTeam
fields = [
"teamstats",
]
depth = 1
Просмотров (То же, что и выше, я провел много тестов с ними, поэтому то, что я привожу ниже, это только самый последний тест)
class StandingsList(generics.ListCreateAPIView):
queryset = Season.objects.order_by('-endDate').all()
serializer_class = StandingsSerializer
def get_queryset(self):
season_id = self.request.query_params.get('season_id')
queryset = SeasonDivisionTeam.objects.filter(season_division__season_id=season_id)
return queryset