Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to have different serializers for read_only & write_only with the same name in DRF?

After you create a Django object in a CreateAPI of DRF, you get a status 201 created and the object is returned with the same serializer you used to create the Django object with.

Wanted: on create: Serializer.comments = Textfield(write_only=True) and on created (201 status) Serializer.comments = a list of commments

I know it's possible by overriding the CreateAPIView.create function. However, I'd like to know if it's possible by using write_only=True and read_only=True attributes to serializer fields.

For now I think it's not possible because they both have the same name. I'd have liked to do something like this using a fake kwarg names actual_name:

class CreateEventSerializer(serializers.ModelSerializer):
    comments_readonly = serializers.SerializerMethodField(read_only=True, actual_name='comments')

class Meta:
    model = Event
    fields = ('id', 'comments', 'comments_readonly')

def __init__(self, *args, **kwargs):
    super(CreateEventSerializer, self).__init__(*args, **kwargs)
    self.fields['comments'].write_only = True

def get_comments_readonly(self, obj):
    comments = obj.comments.replace('\r', '\n')
    return [x for x in comments.split('\n') if x != '']

But this way, the JSON that is returned still contains the key "comments_readonly" instead of the wanted key "comments".

Using latest DRF, 3.7.1

In other words: Is it possible to create a serializer field that behaves differently based on read and write, (using only 1 serializer class)?

like image 911
Michael van de Waeter Avatar asked Nov 08 '22 15:11

Michael van de Waeter


1 Answers

This seems to do the trick for the JSON response, but it feels a bit hacky, as DRF HTML forms now shows a python list in the comments textarea field.

class CreateEventSerializer(serializers.ModelSerializer):

    class Meta:
        model = Event
        fields = ('id', 'comments')

    def get_comments(self, obj):
        comments = obj.comments.replace('\r', '\n')
        return [x for x in comments.split('\n') if x != '']

    def to_representation(self, instance):
        data = super(CreateEventSerializer, self).to_representation(instance)
        data['comments'] = self.get_comments(instance)
        return data
like image 56
Michael van de Waeter Avatar answered Nov 15 '22 06:11

Michael van de Waeter