您好,我有一个序列化程序,我想为GET请求提供一种字段类型,为POST请求提供另一种字段类型。
这些是我的序列化器:
class TypeSerializer(serializers.Serializer):
id = serializers.CharField()
name = serializers.CharField(max_length=50)
colour = serializers.CharField(max_length=8)
class UserSerializer(serializers.Serializer):
id = UUIDField(format="hex_verbose")
name = serializers.CharField()
type = TypeSerializer()
所以响应是这样的:
{
"id": "987328lf-93ad-21ba-2648-h2u7b95d5cf",
"name": "name",
"type": {
"id": "RANDOM_ID",
"name": "Type 1",
"colour": "#ffffff"
}
}
这就是我想要的GET,但是在POST上,我想发送这样的有效负载:
{
"name": "New name",
"type": "RANDOM_ID"
}
我会收到500错误,因为类型应该是字典。
任何人都知道是否有可能在不创建另一个序列化程序的情况下为GET提供一个字段,为POST提供另一个字段吗?
答案 0 :(得分:1)
您需要覆盖 to_internal_value 方法:
class UserSerializer(serializers.Serializer):
id = UUIDField(format="hex_verbose")
name = serializers.CharField()
type = TypeSerializer()
def to_internal_value(self, data):
type = data.get('type')
if type:
data['type'] = {'id': type}
ret = super(UserSerializer, self).to_internal_value(data)
# Probably here you will need to get type instance.
return ret
我认为您想使用此序列化程序来创建用户,因此需要更多改进:
# Inherit from ModelSerializer !
class UserSerializer(serializers.ModelSerializer):
id = UUIDField(format="hex_verbose")
name = serializers.CharField()
type = TypeSerializer()
class Meta:
model = User # Set model
fields = ('id', 'name', 'type') # Set fields
def to_internal_value(self, data):
type = data.get('type')
if type:
data['type'] = {'id': type}
ret = super(UserSerializer, self).to_internal_value(data)
# Here i change dict to instance
type = ret.get('type')
if type:
try:
ret['type'] = Type.objects.get(id=type['id'])
except Type.DoesNotExist:
raise ValidationError({'type': ['Type with the given ID does not exist.']}
return ret
答案 1 :(得分:1)
一种解决方法是使用2个字段-一个读取字段和一个写入字段:
class TypeSerializer(serializers.Serializer):
id = serializers.CharField()
name = serializers.CharField(max_length=50)
colour = serializers.CharField(max_length=8)
class UserSerializer(serializers.Serializer):
id = UUIDField(format="hex_verbose")
name = serializers.CharField()
type_read = TypeSerializer(read_only=True)
# you could use a prrimary key related field
# instead if it is a model serializer;
type = serializers.CharField(write_only=True)
def to_representation(self, instance):
rep = super().to_representation(instance)
# rename type_read to type
rep['type'] = rep['type_read']
del rep['type_read']
return rep