我正在使用Django Rest创建一个简单的API。我需要创建一个用户可以更改他/她密码的视图。我使用的是默认的Django用户模型和一个简单的UserSerializer
。有一种叫做set_password
的方法,但我找不到与用户seriliazer相关的方法。我无法在任何地方找到任何解决方案。
UserSelializer:
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = ('id', "username", 'email', 'first_name', 'last_name', 'password')
View(ClassedBased):这是一个例子(我不知道我在这做什么):
class UserChangePassword(APIView):
def patch(self, request):
user = self.request.user
serialized = UserSerializer(data=request.DATA)
if serialized.is_valid():
user.set_password(serialized.data['password'])
user.save()
return Response(status=status.HTTP_205_RESET_CONTENT)
else:
return Response(serialized.errors, status=status.HTTP_400_BAD_REQUEST)
请注意,我想发布一个json脚本来更改为密码。像这样:
{
"old_password": "123",
"new_password": "12345"
}
答案 0 :(得分:1)
一种方法可能是覆盖Serializer中的restore_object方法。这看起来像这样:
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = ('id', "username", 'email', 'first_name', 'last_name', 'password')
# turn text to hashed password
def restore_object(self, attrs, instance=None):
attrs['password'] = make_password(attrs['password'])
return super(UserSerializer, self).restore_object(attrs, instance=None)
现在,当反序列化为对象实例时,您将拥有有效的哈希密码。然后,您应该能够通过稍微修改您当前拥有的视图来完成您想要的任务。
class UserChangePassword(APIView):
def patch(self, request):
serialized = UserSerializer(data=request.DATA)
if serialized.is_valid():
serialized.save()
return Response(status=status.HTTP_205_RESET_CONTENT)
else:
return Response(serialized.errors, status=status.HTTP_400_BAD_REQUEST)
我相信你的PATCH请求中的JSON(取决于查找类型,我认为默认为id)看起来像这样:
{
"id": "83",
"password": "12345"
}
我希望这有帮助!
编辑:
请注意,正如Symmetric在评论中指出的那样,restore_object
已在DRF 3.0中弃用
答案 1 :(得分:0)
您的问题的回答地址为:https://stackoverflow.com/a/27586192/2950621
不要对视图类中的密码执行任何操作。在set_password
课程中,在重写的create
和update
方法中添加UserSerializer
次来电。
您可以使用patch
创建ModelViewSet
(部分更新)视图,如:
class UserViewSet(viewsets.ModelViewSet):
lookup_field = 'username'
queryset = User.objects.all()
serializer_class = serializers.UserSerializer
根据引用答案中的@DRC,在create
类中添加update
和UserSerializer
方法:
def create(self, validated_data):
user = get_user_model(**validated_data)
user.set_password(validated_data['password'])
user.save()
return user
def update(self, instance, validated_data):
for f in UserSerializer.Meta.fields + UserSerializer.Meta.write_only_fields:
set_attr(instance, f, validated_data[f])
instance.set_password(validated_data['password'])
instance.save()
return instance
此外,您传入的JSON应该更像:
{
"username": "mariodev",
"password": "12345"
}
答案 2 :(得分:0)
Password reset using Viewset
In View
from rest_framework.decorators import detail_route, list_route, permission_classes
from rest_framework import viewsets
class UserProfileViewSet(viewsets.ViewSet):
permission_classes = (AllowAny,)
serializer_class = UserProfileSerializer
def list(self, request):
queryset = UserProfile.objects.all()
serializer = self.serializer_class(queryset, many=True)
return Response(serializer.data)
def create(self, request):
serializer = self.serializer_class(data=request.data)
# check email address is exists or not.
user_type = request.data['user_type']
user_token = register_by_social(request.data['email'], request.data['username'], user_type)
if not user_token or user_token == True:
if not User.objects.filter(Q(email=request.data['email'])
| Q(username=request.data['username'])).exists():
if serializer.is_valid():
userprofile = serializer.save()
return Response({
'status': status.HTTP_201_CREATED,
'message': 'Successfully signup new user.',
'token': userprofile.user.auth_token.key })
return Response({
'status': status.HTTP_400_BAD_REQUEST,
'message': 'Please provided required fields.',
'error' : serializer.errors })
return Response({
'status': status.HTTP_409_CONFLICT,
'message': 'Email address or username is already exists.'})
return Response({
'status': status.HTTP_200_OK,
'message': 'Social user is already registered.',
'token': user_token })
@list_route(permission_classes=[IsAuthenticated], authentication_classes = (BasicAuthentication, TokenAuthentication),
methods=['post'], url_path='reset-user-password')
def reset_user_password(self, request, pk=None):
reset_password_serializer = UserResetPasswordSerializer(request.user, data=request.data)
if reset_password_serializer.is_valid():
if not request.user.check_password(request.data.get('password')):
return Response({"password": ["Wrong password."]}, status=status.HTTP_400_BAD_REQUEST)
request.user.set_password(request.data.get('new_password'))
request.user.save()
return Response({"Message": ["Password reset successfully"]}, status=status.HTTP_200_OK)
You can make a serializer only for password in serializer.py
import django.contrib.auth.password_validation as validators
class UserResetPasswordSerializer(serializers.ModelSerializer):
password = serializers.CharField(source='user.password', style={'input_type': 'password'},
max_length=20, min_length=8)
new_password = serializers.CharField(style={'input_type': 'password'},
max_length=20, min_length=8)
class Meta:
model = User
fields =("password", 'new_password')