8

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:

  • python == 3.6.1
  • Django == 1.11.2
  • djangorestframework == 3.6.3
Rodrigo Braga
  • 139
  • 2
  • 6
  • Have you tried to explicitly declare the `value` field on your serializer as a `serializers.CharField` ? I suspect DRF to create a ReadOnly serializer field for `value` as it is not a field on the model. – Michael Rigoni Jun 22 '17 at 18:01
  • Yes Michael. I need to create explicitly the field like `value = serializers.CharField()` on Serializer. Thank you! – Rodrigo Braga Jun 22 '17 at 18:36

2 Answers2

18

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',)
double-beep
  • 5,031
  • 17
  • 33
  • 41
Michael Rigoni
  • 1,946
  • 12
  • 17
2

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',) 
rom
  • 1,009
  • 9
  • 16