将嵌套数据传递给 Django ModelSerializer

Passing nested data to Django ModelSerializer

我想知道如果嵌套数据的子项本身不是模型,您如何将嵌套数据传递给 ModelSerializer

我正在处理的数据如下所示:

{
  'leadId': 12345,
  'updateTime': 1651250096821,
  'changeInfo': {
    'oldstage': 'New Leads',
    'newstage': 'Attempting Contact'
  }
}

根据以前的经验,我知道如果我只使用 leadIdupdateTime,我的序列化程序将如下所示:

class LogSerializer(serializers.ModelSerializer):
    leadId = serializers.IntegerField(source="lead_id")
    updateTime = serializers.IntegerField(source="update_time")

    class Meta:
        model = Log
        fields = ["leadId", "updateTime"]

这样就可以做到:

data = {
    'leadId': 12345,
    'updateTime': 1651250096821
}
serializer = LogSerializer(data=data)
serializer.is_valid()
serializer.save()

如果我不想将 changeInfo 变成它自己的模型,是否可以将字段映射到嵌套数据?看起来像这样的东西(但这显然行不通):

class LogSerializer(serializers.ModelSerializer):
    leadId = serializers.IntegerField(source="lead_id")
    updateTime = serializers.IntegerField(source="update_time")
    oldstage = serializers.IntegerField(source="oldstage")
    newstage = serializers.IntegerField(source="newstage")


    class Meta:
        model = Log
        fields = ["leadId", "updateTime", "oldstage", "newstage]

您可以为您的 changeInfo 字段使用自定义序列化程序(您不需要为此创建模型):

class ChangeInfoSerializer(serializers.Serializer):
    oldstage = serializers.CharField(max_length=100, source="old_stage") # Set max_length to a value that suits your needs
    newstage = serializers.CharField(max_length=100, source="new_stage")

    def create(self, validated_data):
        pass

    def update(self, instance, validated_data):
        pass


class LogSerializer(serializers.ModelSerializer):
    leadId = serializers.IntegerField(source="lead_id")
    updateTime = serializers.IntegerField(source="update_time")
    changeInfo = ChangeInfoSerializer(required=False) # Change to required=True if you want this field to be mandatory
    

    class Meta:
        model = Log
        fields = ["leadId", "updateTime", "changeInfo"]

    def create(self, validated_data):
        change_info = validated_data.pop('changeInfo')
        for key, value in change_info.items():
            if key == "old_stage":
                validated_data['old_stage'] = value
            elif key == "new_stage":
                validated_data['new_stage'] = value
        log = Log.objects.create(**validated_data)
        return log

    def update(self, instance, validated_data):
        change_info = validated_data.pop('changeInfo')
        
        instance.lead_id = validated_data.get('leadId', instance.lead_id)
        instance.update_time = validated_data.get('updateTime', instance.update_time)
        
        # Here you can use change_info['oldstage'] and change_info['newstage'] if 'changeInfo' is sent (otherwise you'll get a KeyError)
        
        instance.save()
        
        return instance

如评论中所述,SerializerMethodfield 是一个很好的方法:

serializers.py

class LogSerializer(...):

    ...
    changeInfo = serializers.SerializerMethodField()

    def get_changeInfo(self, obj): return {
        "leadId" : obj.lead_id,
        "updateTime": obj.update_time
    }

    class Meta:
        fields = ["changeInfo", ...]
        ...