Передача вложенных данных в Django ModelSerializer
Я хочу узнать, как можно передать вложенные данные в ModelSerializer, если дочерняя часть вложенных данных не является самостоятельной моделью.
Данные, с которыми я работаю, выглядят следующим образом:
{
'leadId': 12345,
'updateTime': 1651250096821,
'changeInfo': {
'oldstage': 'New Leads',
'newstage': 'Attempting Contact'
}
}
Из предыдущего опыта я знаю, что если бы я работал только с leadId и updateTime, мой сериализатор выглядел бы следующим образом:
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) # Set max_length to a value that suits your needs
newstage = serializers.CharField(max_length=100)
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')
log = Log.objects.create(**validated_data)
# Here you can use change_info['oldstage'] and change_info['newstage'] if 'changeInfo' is sent (otherwise you'll get a KeyError)
# You should add your custom logic here, dont forget to call log.save() if you make any updates to the log created
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
Как упоминалось в комментариях, поле SerializerMethod является хорошим способом:
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", ...]
...