Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to make a field in Serializer both readable and writeable

I am writing a Serializer for my model which will be accessed using GET, POST and PATCH endpoints. I have a property in my model which I am using as a source for a field. However, using source= in serializer field is making it ready-only.

If I remove the source="get_field1" from the

field1 = serializers.NullBooleanField(source="get_field1")

then I am able to update the data.

But I HAVE to use the source to get the right value of the field.

class MyModel(models.Model):
    field1 = NullBooleanField(default=None)

    @property
    get_field1(self):
       data = True
       # ...some logic
       return data

Now I have a serializer that I am using

    class MyModelSerializer(serializers.ModelSerializer):
        field1 = serializers.NullBooleanField(source="get_field1")
        class Meta:
             model = MyModel
             fields = ('field1')

Now in my API endpoint, I do this

    serializer = MyModelSerializer(my_model, data=request.data, partial=True)
    if serializer.is_valid():
        serializer.save() # <- throws error "can't set attribute"

Also, I would like to mention that the field in the serializer is referred by the property name and not by the field name.

Example: If I do

>> serializer.validated_data

>> 'OrderedDict(['get_field1'], True) # <- shouldn't this by field1 and not get_field1

like image 365
dhiraj Avatar asked Oct 17 '25 02:10

dhiraj


1 Answers

Answer by @JPG is good, but I feel it's a hacky way.

I would override the to_representation method of the Serializer to achieve your purpose.

Here's what you can do

class MyModelSerializer(serializers.ModelSerializer):
        field1 = serializers.NullBooleanField() # get rid of source

        def to_representation(self, instance):
             data = super(MyModel, self).to_representation(instance)
             data.update({
                  'field1': instance.get_field1
             })
             return data       

        class Meta:
             model = MyModel
             fields = ('field1')

This way you are implicitly providing the source and your field becomes writeable. So every time you GET, POST, or PATCH you'll get the right value.

like image 162
vardos Avatar answered Oct 18 '25 16:10

vardos



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!