如何在Django REST Framework序列化器中实现自定义嵌套数据结构
问题背景
现有客户端采用如下结构发送数据:
{ "hive_metadata": {"name": "hive name"}, "bees": [{"name": "bee 1"}, {"name": "bee 2"}, ...] }
对应的Django模型定义:
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 )
当前通过手动遍历解析数据,希望改用Django REST Framework序列化器重构,但嵌套的hive_metadata字段实现遇到阻碍。已实现能生成不含hive_metadata结构的序列化器:
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",)
该序列化器输出结构:
{ "name": "hive name", "bees": [{"name": "bee 1"}, {"name": "bee 2"}, ...] }
尝试通过子序列化器实现嵌套的hive_metadata,但无法确定source参数值以将同一对象传入内层序列化器:
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",)
请问能否通过Django REST Framework序列化器实现该需求?
解决方案
完全可以实现,只需要将source参数设为self即可,它表示把当前序列化的Hive对象本身传入HiveMetaDataSerializer中。
修改后的序列化器代码如下:
class HiveMetaDataSerializer(ModelSerializer): class Meta: model = models.Hive fields = ("name",) class PopulatedHiveSerializer(ModelSerializer): bees = BeesSerializer(many=True, source="bee_set") # 使用source='self'将当前Hive对象传入子序列化器 hive_metadata = HiveMetaDataSerializer(source='self') class Meta: model = models.Hive fields = ("hive_metadata","bees",)
这样序列化后就能得到客户端需要的结构:
{ "hive_metadata": {"name": "hive name"}, "bees": [{"name": "bee 1"}, {"name": "bee 2"}, ...] }
如果需要支持反序列化(解析客户端传入的数据),还需要在序列化器中添加create方法来处理嵌套数据的保存逻辑,示例如下:
class PopulatedHiveSerializer(ModelSerializer): bees = BeesSerializer(many=True) hive_metadata = HiveMetaDataSerializer(source='self') class Meta: model = models.Hive fields = ("hive_metadata", "bees") def create(self, validated_data): # 提取bees数据 bees_data = validated_data.pop('bees') # 创建Hive实例 hive = Hive.objects.create(**validated_data['hive_metadata']) # 创建关联的Bee实例 for bee_data in bees_data: Bee.objects.create(hive=hive, **bee_data) return hive
内容的提问来源于stack exchange,提问作者kojiro
相关产品推荐
相关产品推荐

