在Django Rest Framework中直接映射深层嵌套JSON至单模型的方法
问题:直接映射两层嵌套的API数据到单个模型序列化器
我需要序列化一个包含location字典的geometry字典(数据来自外部API,嵌套两层),并将其值映射到单个模型。目前通过source='*'实现,但需要为每个嵌套对象新建ModelSerializer,请问是否有方法直接定位到目标嵌套对象?
示例输入数据
{ ... "geometry": { "location": { "lat": ..., "lng": ..., } } ... }
对应的模型
class MyModel(models.Model): # 其他一级属性 latitude = models.CharField(max_length=20) longitude = models.CharField(max_length=20)
当前序列化器实现
class GeometrySerializer(serializers.ModelSerializer): latitude = serializers.DecimalField(max_digits=globals.MAX_DECIMAL_DIGITS, decimal_places=globals.MAX_DECIMAL_PLACES) longitude = serializers.DecimalField(max_digits=globals.MAX_DECIMAL_DIGITS, decimal_places=globals.MAX_DECIMAL_PLACES) class Meta: model = models.Location fields = ['latitude', 'longitude'] class GeometryLocationSerializer(serializers.ModelSerializer): location = GeometrySerializer(source='*') class Meta: model = models.Location fields = ['location'] class LocationSerializer(serializers.ModelSerializer): # 注释掉的直接映射尝试 # latitude = serializers.DecimalField(max_digits=globals.MAX_DECIMAL_DIGITS, decimal_places=globals.MAX_DECIMAL_PLACES, source='geometry.location.lat') # longitude = serializers.DecimalField(max_digits=globals.MAX_DECIMAL_DIGITS, decimal_places=globals.MAX_DECIMAL_PLACES, source='geometry.location.lng') geometry = GeometryLocationSerializer(source='*') class Meta: model = models.Location fields = ['id', 'addr_address', 'business_status', 'formatted_address', 'formatted_phone_number', 'icon', 'icon_background_color', 'icon_mask_base_uri', 'international_phone_number', 'name', 'place_id', 'rating', 'reference', 'url', 'user_ratings_total', 'vicinity', 'website', 'geometry', 'compound_code', 'global_code'] read_only_fields = ['id']
解决方案
完全不需要创建多层嵌套的ModelSerializer,直接在主序列化器中给latitude和longitude字段指定嵌套路径的source即可,直接从两层嵌套结构中取值映射到模型字段,省去额外序列化器的冗余代码。
修改后的序列化器代码:
class LocationSerializer(serializers.ModelSerializer): # 直接通过source定位到两层嵌套的字段 latitude = serializers.DecimalField( max_digits=globals.MAX_DECIMAL_DIGITS, decimal_places=globals.MAX_DECIMAL_PLACES, source='geometry.location.lat' ) longitude = serializers.DecimalField( max_digits=globals.MAX_DECIMAL_DIGITS, decimal_places=globals.MAX_DECIMAL_PLACES, source='geometry.location.lng' ) class Meta: model = models.Location fields = ['id', 'addr_address', 'business_status', 'formatted_address', 'formatted_phone_number', 'icon', 'icon_background_color', 'icon_mask_base_uri', 'international_phone_number', 'name', 'place_id', 'rating', 'reference', 'url', 'user_ratings_total', 'vicinity', 'website', 'compound_code', 'global_code', 'latitude', 'longitude'] read_only_fields = ['id']
说明
- 序列化器会自动从传入数据的
geometry.location.lat和geometry.location.lng路径取值,直接映射到模型的latitude和longitude字段。 - 如果需要在序列化输出时保留
geometry.location的嵌套结构,可以结合SerializerMethodField自定义输出格式,但如果只是完成数据到单个模型的映射,上述方法最简洁高效。
内容的提问来源于stack exchange,提问作者JayaAnim
相关产品推荐
相关产品推荐

