我有一个像这样的序列化器:
class DataSetColumnSerializer(serializers.ModelSerializer):
custom_target = target_serializers.CustomTargetSerializer()
class Meta:
model = dataset_models.DataSetColumn
custom_target
使用以下序列化程序:
class CustomTargetSerializer(serializers.ModelSerializer):
class Meta:
model = target_models.CustomTarget
我正在传回一个对象,其中包含我要为custom_target
设置的DataSetColumn
。当我验证序列化程序并保存它时:
serializer = serializers.DataSetColumnSerializer(column, data=request.DATA)
if serializer.is_valid():
serializer.save()
custom_target
序列化程序正在创建新的CustomTarget
,而不是仅将custom_target
的{{1}}设置为传入的对象。我尝试设置{{1}只读。这是因为它不会创建新的DataSetColumn
,但也不会将CustomTargetSerializer
设置为对象。
如何在序列化CustomTarget
对象上使用custom_target
将serializer.save()
设置为传入的嵌套对象,而不是从嵌套对象创建新对象?
答案 0 :(得分:0)
这是一个相当'脏'这样做的方法:
在 pre_save 处理程序中,您可以将 custom_target 重置为仅具有ID。像这样:
def pre_save(self, obj):
if 'custom_target' in self.request.DATA:
custom_target = self.request.DATA['custom_target']
self.request.DATA['custom_target'] = custom_target['id']
现在无法想到任何更好/更清洁的解决方案,但如果找到一个,我会写出来:)
答案 1 :(得分:0)
在我看来,REST Framework中最常见的解决方案是分别使用嵌套的序列化程序和PrimaryKeyRelatedField
。有了它,您可以将CustomTarget
嵌套对象作为custom_target
接收,并且可以在创建提供CustomTarget
作为POST参数时将custom_target_id
个对象与其关联。
class DataSetColumnSerializer(serializers.ModelSerializer):
custom_target = target_serializers.CustomTargetSerializer(read_only=True)
custom_target_id = serializers.PrimaryKeyRelatedField(source='custom_target')
class Meta:
model = dataset_models.DataSetColumn
但是,您最终会得到两个属性custom_target
和custom_target_id
,这些属性可能不会被视为理想选择。作为通用解决方案,可以实现自定义字段。
通用方法:自定义相关字段
class NestedRelatedField(serializers.PrimaryKeyRelatedField):
def __init__(self, serializer_class, *args, **kwargs):
self.serializer = serializer_class()
super(NestedRelatedField, self).__init__(queryset=serializer_class.Meta.model.objects.all(), *args, **kwargs)
def to_representation(self, instance):
return self.serializer.to_representation(instance)
将其用作:
class DataSetColumnSerializer(serializers.ModelSerializer):
custom_target = NestedRelatedField(CustomTargetSerializer)