Hide password field in GET but not POST in Django REST Framework where depth=1 in serializer

独自空忆成欢 提交于 2020-07-08 22:19:56

问题


I have 2 models : User & UserSummary. UserSummary has a foreign key to User. I just noticed that if I set depth= 1 within UserSummarySerializer, the password field is included in the output. It's hashed, but it would still be best to exclude this field.

To hide the password field, I've just set the user field explicitly in the serializer, just like this :

class UserSerializer(serializers.ModelSerializer):
    """A serializer for our user profile objects."""

    class Meta:
        model = models.User
       extra_kwargs = {'password': {'write_only': True}}
        exclude = ('groups', 'last_login', 'is_superuser', 'user_permissions', 'created_at')

    def create(self, validated_data):
        """Create and return a new user."""

        user = models.User(
            email = validated_data['email'],
            firstname = validated_data['firstname'],
            lastname = validated_data['lastname'],
            mobile = validated_data['mobile']
        )

        user.set_password(validated_data['password'])
        user.save()

        return user


class UserSummarySerializer(serializers.ModelSerializer):
    user = UserSerializer()

    class Meta:
        model = models.UserSummary
        fields = '__all__'
        depth = 1

The downside of this way of doing is that, the field password is not available anymore on the POST request when creating a new user.

How could I hide the password field on the GET request of UserSummary but display it in the POST request of User ?


回答1:


This is complicated when you put all the function serializer to one, I would create a UserCreateSerializer in this scenario:

class UserCreateSerializer(serializers.ModelSerializer):
    """A serializer for our user profile objects."""

    class Meta:
        model = models.User
        extra_kwargs = {'password': {'write_only': True}}
        fields = ['username', 'password', 'email', 'firstname', 'lastname', 'mobile'] # there what you want to initial.

    def create(self, validated_data):
        """Create and return a new user."""

        user = models.User(
            email = validated_data['email'],
            firstname = validated_data['firstname'],
            lastname = validated_data['lastname'],
            mobile = validated_data['mobile']
        )

        user.set_password(validated_data['password'])
        user.save()

        return user

Then you can use the UserCreateSerializer in your UserCreateAPIView.




回答2:


The trick here is to include the 'password' field in the "fields" tuple so that password shows in BOTH 'GET' and 'POST', and then add 'extra_kwargs' to force 'password' field ONLY to appear in 'POST' form. Code as below:

class UserSerializer(serializers.HyperlinkedModelSerializer):
    class Meta:
        model = User
        fields = ('url', 'username', 'email',
              'is_active', 'is_staff', 'is_superuser', 'password',)

        # These fields are displayed but not editable and have to be a part of 'fields' tuple
        read_only_fields = ('is_active', 'is_staff', 'is_superuser',)

        # These fields are only editable (not displayed) and have to be a part of 'fields' tuple
        extra_kwargs = {'password': {'write_only': True, 'min_length': 4}}



回答3:


class UserSerializer(serializers.ModelSerializer):

    class Meta:
        model = User

    def to_representation(self, obj):
        rep = super(UserSerializer, self).to_representation(obj)
        rep.pop('password', None)
        return rep



回答4:


To Make your password to not show password, you need to change style like following-

password = serializers.CharField(
    style={'input_type': 'password'}
    )

That's it. I hope it helps.



来源:https://stackoverflow.com/questions/48480972/hide-password-field-in-get-but-not-post-in-django-rest-framework-where-depth-1-i

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!