wake-up-neo.com

Wie kann ich das Benutzerpasswort in Django Rest Framework aktualisieren?

Ich möchte darum bitten, dass der folgende Code ein Kennwort zur Aktualisierung bereitstellt, aber ich möchte das Kennwort nach dem aktuellen Kennwortbestätigungsvorgang aktualisieren. Also, was soll ich dazu hinzufügen? Vielen Dank.

class UserPasswordSerializer(ModelSerializer):

    class Meta:
        model = User
        fields = [
            'password'
        ]

        extra_kwargs = {
            "password": {"write_only": True},
        }

    def update(self, instance, validated_data):
        for attr, value in validated_data.items():
            if attr == 'password':
                instance.set_password(value)
            else:
                setattr(instance, attr, value)
        instance.save()
        return instance
22
bysucpmeti

Ich glaube, dass die Verwendung eines Modelserializers ein Overkill sein kann. Dieser einfache Serializer sollte funktionieren.

Serializers.py

from rest_framework import serializers

class ChangePasswordSerializer(serializers.Serializer):

    """
    Serializer for password change endpoint.
    """
    old_password = serializers.CharField(required=True)
    new_password = serializers.CharField(required=True)

Views.py

from rest_framework import status
from rest_framework import generics
from rest_framework.response import Response
from Django.contrib.auth.models import User
from . import serializers
from rest_framework.permissions import IsAuthenticated   

class ChangePasswordView(UpdateAPIView):
        """
        An endpoint for changing password.
        """
        serializer_class = ChangePasswordSerializer
        model = User
        permission_classes = (IsAuthenticated,)

        def get_object(self, queryset=None):
            obj = self.request.user
            return obj

        def update(self, request, *args, **kwargs):
            self.object = self.get_object()
            serializer = self.get_serializer(data=request.data)

            if serializer.is_valid():
                # Check old password
                if not self.object.check_password(serializer.data.get("old_password")):
                    return Response({"old_password": ["Wrong password."]}, status=status.HTTP_400_BAD_REQUEST)
                # set_password also hashes the password that the user will get
                self.object.set_password(serializer.data.get("new_password"))
                self.object.save()
                return Response("Success.", status=status.HTTP_200_OK)

            return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
43
Yiğit Güler

@ Yiğit Güler gibt eine gute Antwort, danke, aber es könnte in einigen kleineren Punkten besser sein.

Solange Sie nicht wirklich mit UpdateModelMixin arbeiten, aber direkt mit der Anforderungsbenutzerinstanz, brauchen Sie kein UpdateAPIView . Ein einfacher APIView reicht aus.

Wenn das Kennwort geändert wird, können Sie auch einen status.HTTP_204_NO_CONTENT anstelle eines 200 mit zufälligem Inhalt zurückgeben.

Vergessen Sie nicht, Ihr neues Passwort vor dem Speichern zu bestätigen. Es ist zu schade, wenn Sie bei der Aktualisierung "Kennwort" zulassen, wenn Sie nicht bei der Erstellung arbeiten.

Also benutze ich den folgenden Code in meinem Projekt:

from Django.contrib.auth.password_validation import validate_password

class ChangePasswordSerializer(serializers.Serializer):
    """
    Serializer for password change endpoint.
    """
    old_password = serializers.CharField(required=True)
    new_password = serializers.CharField(required=True)

    def validate_new_password(self, value):
        validate_password(value)
        return value

Und für die Aussicht:

class UpdatePassword(APIView):
    """
    An endpoint for changing password.
    """
    permission_classes = (permissions.IsAuthenticated, )

    def get_object(self, queryset=None):
        return self.request.user

    def put(self, request, *args, **kwargs):
        self.object = self.get_object()
        serializer = ChangePasswordSerializer(data=request.data)

        if serializer.is_valid():
            # Check old password
            old_password = serializer.data.get("old_password")
            if not self.object.check_password(old_password):
                return Response({"old_password": ["Wrong password."]}, 
                                status=status.HTTP_400_BAD_REQUEST)
            # set_password also hashes the password that the user will get
            self.object.set_password(serializer.data.get("new_password"))
            self.object.save()
            return Response(status=status.HTTP_204_NO_CONTENT)

        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
11
tominardi

Nachdem Sie den Benutzer gespeichert haben, möchten Sie möglicherweise sicherstellen, dass der Benutzer angemeldet bleibt (nach Django == 1.7 wird ein Benutzer automatisch bei der Kennwortänderung abgemeldet):

from Django.contrib.auth import update_session_auth_hash

# make sure the user stays logged in
update_session_auth_hash(request, self.object)

Ich denke, die einfachste Lösung (wenn ich am einfachsten sage, meine ich die kürzeste mögliche und sauberere Lösung) wäre etwa so:

Klasse anzeigen

class APIChangePasswordView(UpdateAPIView):
    serializer_class = UserPasswordChangeSerializer
    model = get_user_model() # your user model
    permission_classes = (IsAuthenticated,)

    def get_object(self, queryset=None):
        return self.request.user

Serialisiererklasse

from rest_framework import serializers
from rest_framework.serializers import Serializer


class UserPasswordChangeSerializer(Serializer):
    old_password = serializers.CharField(required=True, max_length=30)
    password = serializers.CharField(required=True, max_length=30)
    confirmed_password = serializers.CharField(required=True, max_length=30)

    def validate(self, data):
        # add here additional check for password strength if needed
        if not self.context['request'].user.check_password(data.get('old_password')):
            raise serializers.ValidationError({'old_password': 'Wrong password.'})

        if data.get('confirmed_password') != data.get('password'):
            raise serializers.ValidationError({'password': 'Password must be confirmed correctly.'})

        return data

    def update(self, instance, validated_data):
        instance.set_password(validated_data['password'])
        instance.save()
        return instance

    def create(self, validated_data):
        pass

    @property
    def data(self):
        # just return success dictionary. you can change this to your need, but i dont think output should be user data after password change
        return {'Success': True}
0
Igor

serializer.py

class UserSer(serializers.ModelSerializers):
      class meta:
          model=UserModel
          fields = '__all__'

views.py

class UserView(UpdateAPIView):
    serializer_class = serializers.UserSer
    queryset = models.User.objects.all()

    def get_object(self,pk):
        try:
            return models.User.objects.get(pk=pk)
        except Exception as e:
            return Response({'message':str(e)})

    def put(self,request,pk,format=None):
        user = self.get_object(pk) 
        serializer = self.serializer_class(user,data=request.data)

        if serializer.is_valid():            
            serializer.save()
            user.set_password(serializer.data.get('password'))
            user.save()
            return Response(serializer.data)    
        return Response({'message':True})
0
Anar Ali