0

I use DRF ModelViewSet for user account CRUD operations. I have "extend" Django user model with Profile model to store complementary user's informations. I have override create and update methods in my serializer to manage nested (related) fields of Profile model.

Using GET and POST methods is OK. In POST, password is correctly created and store (encrypted PBKDF2) in my Postgresql database.

My issue deals with PUT and PATCH methods. When using PATCH or PUT methods, when submitting password and password2, password is stored in database as plaintext.

I've try using make_password() and set_password(make_password()) but neither works. I've read DRF documentation and read many posts in SO but could not find any explanation.

Hope someone could explain this behavior and maybe haw to resolve this issue.

Serializers.py

class RegisterSerializer(serializers.ModelSerializer):
    profile = ProfileSerializer(required=True)
    email = serializers.EmailField(required=True,validators=[UniqueValidator(queryset=User.objects.all())])
    password = serializers.CharField(write_only=True, required=True, validators=[validate_password])
    password2 = serializers.CharField(write_only=True, required=True)
    days_since_joined = serializers.SerializerMethodField()

    class Meta:
        model = User
        fields = ('username', 'password', 'password2', 'email', 'first_name', 'last_name', 'profile', 'days_since_joined')
        extra_kwargs = {
            'first_name': {'required': True},
            'last_name': {'required': True}
        }
       
    def validate(self, attrs):
        password = attrs.get('password')
        password2 = attrs.get('password2')
        if password and password != password2:
            raise serializers.ValidationError({"password": "Password fields didn't match."})
        return attrs

    def get_days_since_joined(self, obj):
        return (now() - obj.date_joined).days

    def create(self, validated_data):
        profile_data = validated_data.pop('profile')
        user = User.objects.create(
            username=validated_data['username'],
            email=validated_data['email'],
            first_name=validated_data['first_name'],
            last_name=validated_data['last_name']
        )
        # create profile
        Profile.objects.create(
            user=user,
            qr_code=profile_data.get('qr_code'),
            backup=profile_data.get('backup'),
            role_in_study=profile_data.get('role_in_study'),
        )
        user.set_password(validated_data['password'])
        user.save()
        return user

    def update(self, instance, validated_data):
        profile_data = validated_data.pop('profile', {})
        profile = instance.profile
        for key, value in profile_data.items():
            setattr(profile, key, value)
        profile.save()
        return super().update(instance, validated_data)

1 Answer 1

0

I think you are missing set_password in your update method.

Sign up to request clarification or add additional context in comments.

1 Comment

In code posted set_password in not mentionned I've try without any effect (user.set_password(make_password(password) neither)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.