Django休息更改用户密码视图

时间:2014-04-24 17:32:40

标签: python django rest django-rest-framework

我正在使用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"
}

3 个答案:

答案 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课程中,在重写的createupdate方法中添加UserSerializer次来电。

您可以使用patch创建ModelViewSet(部分更新)视图,如:

class UserViewSet(viewsets.ModelViewSet):
    lookup_field = 'username'
    queryset = User.objects.all()
    serializer_class = serializers.UserSerializer

根据引用答案中的@DRC,在create类中添加updateUserSerializer方法:

   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')