Reputation: 7170
Hello I have a serialiser and I'd like to have one field type for the GET requests and anther field for the POST requests.
These are my serialisers:
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()
So the response is something like this:
{
"id": "987328lf-93ad-21ba-2648-h2u7b95d5cf",
"name": "name",
"type": {
"id": "RANDOM_ID",
"name": "Type 1",
"colour": "#ffffff"
}
}
That's what I want on the GET, but on the POST I'd like to send a payload like this:
{
"name": "New name",
"type": "RANDOM_ID"
}
I will get a 500 error because type is expected to be a dictionary.
Anyone knows if its posible to have one field for GET and another field for POST without creating another serialiser?
Upvotes: 2
Views: 2491
Reputation: 6296
One way of going about this is using 2 fields - a read field and a write field:
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
Upvotes: 2
Reputation: 752
You need to override to_internal_value method:
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
I think that you want to use this serializer for creating user so it needs so more iprovements:
# 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
Upvotes: 2