次のコードがパスワードの更新を提供するように依頼したいのですが、現在のパスワード確認プロセスの後にパスワードを更新したいです。それで何を追加すればいいですか?ありがとうございました。
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
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)
@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)
ユーザーを保存した後、ユーザーがログインしたままであることを確認したい場合があります(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)
最も簡単な(私が最も簡単に言うとき、私は可能な限り短くてきれいなことを意味する)解決策は次のようなものになると思います:
クラスを見る
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}
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})