DRF | Не может устанавливать оба `read_only` и` write_only` - PullRequest
0 голосов
/ 07 марта 2019

В моем проекте я хочу установить пароль как read_only (потому что у меня есть отдельная конечная точка для сброса пароля) и write_only (потому что я не хочу отправлять пароль в ответе).

Вот мой сериализатор:

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

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

Но я получаю сообщение об ошибке:

AssertionError в / api / user / 21 /

Может не устанавливать как read_only, так и write_only

Как я могу получить поле read_only и write_only?

Ответы [ 3 ]

2 голосов
/ 07 марта 2019

Переопределить метод __init__() сериализатора как,

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

    <b>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</b>

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

Переменная some_flag - это то, что вы должны передать сериализатору либо из представления сброса пароля, либо из другого представления

1 голос
/ 20 мая 2019

Так что распространяясь на ответ @ JPG

Сериализатор

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

И набор просмотра

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

Это позволит писать имя на POST и читать только все остальное

0 голосов
/ 07 марта 2019

хорошо - обычно, если у вас есть две конечные точки, использующие похожий сериализатор, который должен отличаться только определенным полем / функциональностью, вы создаете базовый класс и абстрагируете его и изменяете только те части, которые необходимо изменить.Вот что я бы сделал.

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} }

Теперь UserSerializerForOtherView наследует то же поведение, что и UserSerializer, и теперь у вас также есть новый сериализатор, если вы хотите расширить функциональность только на этом сериализаторе.

Все, что вам нужнонужно будет указать другому представлению использовать другой сериализатор.

...