Сериализаторы Django, как показать данные во вложенном сериализаторе bridge model
Я использую Django REST Framework
.
У меня есть 3 разные модели, 2 из них - отдельные, а 3-я - bridge model
, которая соединяет первые 2 модели
# First standalone model
class Build(TimeStampedModel):
name = models.CharField(max_length=64, null=False, blank=False)
type = models.CharField(max_length=64, null=False, blank=False)
play_as = models.CharField(max_length=64, null=False, blank=False)
link = models.CharField(max_length=255, null=False, blank=False)
class Meta:
ordering = ['-created_at']
def __str__(self):
return f'{self.play_as} - {self.name}'
# Second standalone model
class Run(TimeStampedModel):
name = models.CharField(max_length=64, null=False, blank=False)
difficulty = models.CharField(max_length=64, null=False, blank=False)
origin = models.CharField(max_length=64, null=False, blank=False)
alignment = models.CharField(max_length=64, null=False, blank=False)
class Meta:
ordering = ['-created_at']
def __str__(self):
return f'{self.name} - {self.difficulty}'
# Bridge model
class RunBuild(TimeStampedModel):
run = models.ForeignKey(
Run, related_name='runBuild_run', on_delete=models.CASCADE, null=False, blank=False
)
build = models.ForeignKey(
Build, related_name='runBuild_builds', on_delete=models.CASCADE, null=False, blank=False
)
class Meta:
ordering = ['-run']
def __str__(self):
return f'{self.run.name} - {self.build.name}'
Сериализатор Build
в порядке, проблема стоит в сериализаторах RunBuild
и Run
.
# Model Serializer for Build model
class BuildSerializer(serializers.ModelSerializer):
created_at = serializers.SerializerMethodField()
class Meta:
model = Build
exclude = ['updated_at']
def get_created_at(self, instance):
return instance.created_at.strftime('%B %d, %Y')
# Model Serializer for RunBuild model
class RunBuildSerializer(serializers.ModelSerializer):
# This doesn't work
runBuild_builds = BuildSerializer(many=True, read_only=True)
created_at = serializers.SerializerMethodField()
class Meta:
model = RunBuild
fields = ['run', 'build', 'created_at', 'runBuild_builds']
def get_created_at(self, instance):
return instance.created_at.strftime('%B %d, %Y')
# Model Serializer for Run model
class RunSerializer(serializers.ModelSerializer):
# This works
runBuild_run = RunBuildSerializer(many=True, read_only=True)
created_at = serializers.SerializerMethodField()
class Meta:
model = Run
fields = [
'name',
'difficulty',
'origin',
'alignment',
'created_at',
'runBuild_run'
]
def get_created_at(self, instance):
# We will format the date
return instance.created_at.strftime('%B %d, %Y')
А Run
состоит из нескольких полей и множества Builds
под ними, поэтому мне понадобилась модель моста. Я могу показать множество RunBuild
в сериализаторе Run
, например, так
{
"name": "Versatile Bard",
"difficulty": "Tactician",
"origin": "The Dark Urge",
"alignment": "Chaotic Neutral",
"created_at": "March 14, 2024",
"runBuild_run": [
{
"run": 1,
"build": 1,
"created_at": "March 14, 2024"
},
{
"run": 1,
"build": 2,
"created_at": "March 14, 2024"
},
....
]
}
Но если я сделаю то же самое для сериализатора RunBuild
, он ничего не покажет (а я хочу, чтобы он показывал каждый Build
на нем)
{
"run": 1,
"build": 1,
"created_at": "March 14, 2024"
"runBuild_builds": [
{
"name": "Cleric / Bard - CC / Versatile Spellcaster",
"type": "Main Character",
"play_as": "Main Character",
"link": "......."
},
....
]
}
Поле runBuild_builds
отсутствует в ответе, я добавил его вручную, чтобы показать, как оно должно быть.
В конечном итоге в сериализаторе Run
должен получиться результат, подобный этому
{
"name": "Versatile Bard",
"difficulty": "Tactician",
"origin": "The Dark Urge",
"alignment": "Chaotic Neutral",
"created_at": "March 14, 2024",
"runBuild_run": [
{
"run": 1,
"build": 1,
"created_at": "March 14, 2024",
"runBuild_builds": [
{
"name": "Cleric / Bard - CC / Versatile Spellcaster",
"type": "Main Character",
"play_as": "Main Character",
"link": "......."
},
....
]
},
....
]
}
Есть идеи, как изменить мой код?
Обновите свой RunBuildSerializer
следующим образом,
class RunBuildSerializer(serializers.ModelSerializer):
# This doesn't work
build = BuildSerializer(many=True, read_only=True)
created_at = serializers.SerializerMethodField()
class Meta:
model = RunBuild
fields = ['run', 'build', 'created_at']
def get_created_at(self, instance):
return instance.created_at.strftime('%B %d, %Y')
Удалите поля runBuild_builds
из этого сериализатора. Поскольку это поле related_name, оно должно использоваться, когда нам нужно получить доступ к RunBuild
классу из Build
класса.