web-dev-qa-db-ja.com

Django Rest Framework?

次のコードがパスワードの更新を提供するように依頼したいのですが、現在のパスワード確認プロセスの後にパスワードを更新したいです。それで何を追加すればいいですか?ありがとうございました。

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
24
bysucpmeti

Modelserializerの使用はやり過ぎかもしれないと思います。このシンプルなシリアライザーとビューは動作するはずです。

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)
51
Yiğit Güler

@YiğitGülerが良い答えをくれました、ありがとう。

pdateModelMixinで実際に動作しない限り、リクエストユーザーインスタンスで直接動作する限り、pdateAPIViewを使用する必要はありません。単純なAPIViewで十分です。

また、パスワードが変更されると、status.HTTP_204_NO_CONTENTランダムなコンテンツを含む200ではなく。

ところで、保存する前に新しいパスワードを検証するのを忘れないでください。作成時ではなく、更新時に「パスワード」を許可するのはあまりにも悪いことです。

そこで、プロジェクトで次のコードを使用します。

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

そして、ビューのために:

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)
12
tominardi

ユーザーを保存した後、ユーザーがログインしたままであることを確認したい場合があります(Django == 1.7の後、ユーザーはパスワードの変更時に自動的にログアウトされます)。

from Django.contrib.auth import update_session_auth_hash

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

最も簡単な(私が最も簡単に言うとき、私は可能な限り短くてきれいなことを意味する)解決策は次のようなものになると思います:

クラスを見る

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

シリアライザークラス

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}
1
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})
1
Anar Ali