Rodrigo Braga
Rodrigo Braga

Reputation: 143

Problems to serialize property (getter and setter) from a model using Django Rest Framework

I want to use a property (including setter) from my model in a Serializer, but apparently, the setter is never called.

models.py

class Awesome(models.Model):
    _value = models.TextField()
    def set_value(self, value):
        self._value = value
    def get_value(self):
        return self._value
    value = property(get_value, set_value)

serializers.py

class AwesomeSerializer(serializers.ModelSerializer):
    class Meta:
        model = Awesome
        fields = ('value',)

views.py

class AwesometViewSet(viewsets.ModelViewSet):
    queryset = Awesome.objects.all()
    serializer_class = AwesomeSerializer

On this scenario suggested above, when I make a GET the getter work fine, but when I make a POST the serializer doesn't call the setter.

What wrong I made?!

I am using following versions:

Upvotes: 8

Views: 6902

Answers (2)

Michael Rigoni
Michael Rigoni

Reputation: 1966

You are using ModelSerializer which automatically creates read-write fields on the serializer based on the fields on the model. When it is not a field (a property or a method) and declared in Meta.fields, it defaults to a read only field.

Declaring it explicitly on the serializer will make it a RW field:

class AwesomeSerializer(serializers.ModelSerializer):
    value = serializers.CharField()
    class Meta:
        model = Awesome
        fields = ('value',)

Upvotes: 18

rom
rom

Reputation: 1049

Instead of using getter and setter in the serializer, you can create a custom Field class and override the functions:

  • to_representation - instead the getter
  • to_internal_value - instead the setter

For example:

class ParamsField(serializers.JSONField):
    def to_representation(self, obj):
        # Use the method `get_params` from the Awesome class
        return Awesome.get_params(obj)

    def to_internal_value(self, data):
        # Set the key `date` just for the example
        data["date"] = datetime.datetime.now().isoformat()
        return data


class AwesomeSerializer(serializers.ModelSerializer):
    value = ParamsField()

    class Meta:
        model = Awesome
        fields = ('value',) 

Upvotes: 2

Related Questions