[Django]-May not set both `read_only` and `write_only`

3👍

Override the __init__() method of the serializer as,

class UserSerializer(serializers.ModelSerializer):
    """A Serizlier class for User """

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        if self.context['some_flag']:
            self.fields['password'].read_only = True
        else:
            self.fields['password'].write_only = True

    class Meta:
        model = models.User
        fields = ('id', 'email', 'phone_number', 'user_type', 'password')
        # extra_kwargs = { 'password': { 'write_only': True} } # remove this
        # read_only_fields = ('password',) # remove this

The some_flag variable is something that you should pass to the serializer either from the password reset view or from the other view

👤JPG

2👍

So extending on the answer of @JPG

The Serializer

class ProfileSerializer(serializers.ModelSerializer):
    name = serializers.CharField()

def __init__(self, *args, **kwargs):
    super().__init__(*args, **kwargs)
    if 'create_method' in self.context:
        self.fields['name'].write_only = True
    else:
        self.fields['name'].read_only = True

And the view set

class ProfileViewSet(viewsets.ModelViewSet):
    serializer_class = ProfileSerializer

def get_serializer_context(self):

    # Call Parent
    context = super().get_serializer_context()

    # Check If This Is a POST
    if self.request.method == 'POST':
        context['create_method'] = True

    # Handoff
    return context

This will allow name to be written on POST and read only on everything else

0👍

well – normally if you have two endpoints using a similar serializer which needs to differ only with a certain field/functionality you would create a base class and abstract it and only change/modify the parts of it that need to change. Here is what I would do.

class (serializers.ModelSerializer):
    """A Serizlier class for User """

    class Meta:
        model = models.User
        fields = ('id', 'email', 'phone_number', 'user_type', 'password')
        extra_kwargs = { 'password': { 'read_only': True} }


class UserSerializerForOtherView(UserSerializer):

    class Meta(UserSerializer.Meta):
        extra_kwargs = { 'password': { 'write_only': True} }

Now UserSerializerForOtherView inherits the same behaviour as UserSerializer and you now also have a new serializer should you want to further expand on functionality on this serializer alone.

All you will need to do is tell the other view to use the other serializer.

Leave a comment