An existing client is already sending data in a structure like…
{
"hive_metadata": {"name": "hive name"},
"bees": [{"name": "bee 1", "name": "bee 2", ...}]
}
For models like:
class Hive(models.Model):
name = models.CharField(max_length=32, help_text="name")
class Bee(models.Model):
name = models.CharField(max_length=32, help_text="name")
hive = models.ForeignKey(
Hive, help_text="The Hive associated with this Bee", on_delete=models.CASCADE
)
The code that makes this possible manually iterates over the incoming data. I would like to rewrite it using a django rest framework serializer; however, the fact that hive_metadata
is nested itself has stumped me so far.
If I write
class BeesSerializer(ModelSerializer):
class Meta:
model = models.Bee
fields = ("name",)
class PopulatedHiveSerializer(ModelSerializer):
bees = BeesSerializer(many=True, source="bee_set")
class Meta:
model = models.Hive
fields = ("name","bees",)
would produce
{
"name": "hive name",
"bees": [{"name": "bee 1", "name": "bee 2", ...}]
}
readily enough. I had hoped I could solve it with a reference to a sub-serializer, something like
class HiveMetaDataSerializer(ModelSerializer):
class Meta:
model = models.Hive
fields = ("name",)
class PopulatedHiveSerializer(ModelSerializer):
bees = BeesSerializer(many=True, source="bee_set")
hive_metadata = HiveMetaDataSerializer(source=???)
class Meta:
model = models.Hive
fields = ("hive_metadata","bees",)
but I can't seem to figure out what to put in the "source" so that the same object is passed through the outer serializer into the inner.
So, is there a way to do this using a django rest framework serializer?
You can use a string literal with an asterisk ('*'
), as specified in the documentation [drf-doc]:
The
value source='*'
has a special meaning, and is used to indicate that the entire object should be passed through to the field. This can be useful for creating nested representations, or for fields which require access to the complete object in order to determine the output representation.
so we can use:
class PopulatedHiveSerializer(ModelSerializer):
bees = BeesSerializer(many=True, source='bee_set')
hive_metadata = HiveMetaDataSerializer(source='*')
class Meta:
model = models.Hive
fields = (
'hive_metadata',
'bees',
)