如何在django rest框架中更新Auth用户的密码

How to update password of Auth user in django rest framework

我是 django 休息框架的新手。我正在使用 reactJs 和 django 实现一个简单的登录、注册和忘记密码功能。所有功能都运行良好,但我面临的问题是,在注册时,数据库中的密码被加密然后保存在数据库中,但在更新密码时,新密码保存的与用户输入的密码完全相同。我希望它也像在注册时加密一样在数据库中加密。

我的serializer.py文件

from dataclasses import fields
from rest_framework import serializers
from rest_framework_jwt.settings import api_settings
from django.contrib.auth.models import User


class UserSerializer(serializers.ModelSerializer):

    class Meta:
        model = User
        fields='__all__'
        # fields = ('username','first_name', 'last_name', 'email')


class UserSerializerWithToken(serializers.ModelSerializer):

    token = serializers.SerializerMethodField()
    password = serializers.CharField(write_only=True)

    def get_token(self, obj):
        jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER
        jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER

        payload = jwt_payload_handler(obj)
        token = jwt_encode_handler(payload)
        return token

    def create(self, validated_data):
        password = validated_data.pop('password', None)
        instance = self.Meta.model(**validated_data)
        if password is not None:
            instance.set_password(password)
        instance.save()
        return instance

    

    class Meta:
        model = User
        fields = ('token','first_name', 'last_name','email', 'username', 'password')

我的views.py文件

from asyncio.windows_events import NULL
from django.http import Http404, HttpResponseRedirect
from django.contrib.auth.models import User
from rest_framework import viewsets, permissions, status
from rest_framework.decorators import api_view
from rest_framework.response import Response
from rest_framework.views import APIView
from .serializers import UserSerializer
from .serializers import UserSerializerWithToken
class UserViewSet(viewsets.ModelViewSet):
    serializer_class = UserSerializer
    queryset = User.objects.all()


@api_view(['GET'])
def current_user(request):
    """
    Determine the current user by their token, and return their data
    """
    
    serializer = UserSerializer(request.user)
    return Response(serializer.data)

@api_view(['GET'])
def get_user(request):
    """
    Filter the user wrt username and return the user data and token
    """
    user=User.objects.filter(email=request.query_params['email'])
    serializer = UserSerializer(instance=user, many=True)
    if user.exists():
        return Response(serializer.data)
    else:
        return Response(serializer.errors)


# ########################################################
# This is my update user api to update password
# it updates the password but not encrypting the password 
# like signup encrypts in database
# ########################################################
@api_view(['PUT'])
def update_user(request,id):
    user=User.objects.get(pk=id)
    # userdata={'id':user.id,'username':user.username,'first_name':user.first_name,'last_name':user.last_name,'password':user.password}
    serializer=UserSerializer(instance=user, data=request.data[0])
    if serializer.is_valid():
        serializer.save()
        return Response(serializer.data)
    else:
        return Response(serializer.errors)




class UserList(APIView):
    """
    Create a new user. It's called 'UserList' because normally we'd have a get
    method here too, for retrieving a list of all User objects.
    """

    # permission_classes = (permissions.AllowAny,)

    def post(self, request, format=None):
        serializer = UserSerializerWithToken(data=request.data)
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data, status=status.HTTP_201_CREATED)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

    
    # ############################################################################
    #   I tried the following way as well but it doesn't even update the password
    # ############################################################################
    # 
    #  def put(self,request,id,format=None):
    #     user=User.objects.get(pk=id)
    #     serializer=UserSerializerWithToken(instance=user, data=request.data)
    #     if serializer.is_valid():
    #         serializer.save()
    #         return Response(serializer.data)
    #     else:
    #         return Response(serializer.errors)

        

这是我用于 api

的 url
path('users/<int:id>/',UserList.as_view()),

这就是我从 reactjs

中调用这个 api 的方式
function handleSubmit(e) {
    let user=JSON.parse(localStorage.getItem('matched_user_token'))[0]
    user.password=new_password
    e.preventDefault()
    if (ValidatePassword()) {
      fetch('http://localhost:8000/core/users/'+user.id+'/', {
        method: 'PUT',
        headers: {
          'Content-Type': 'application/json'
        },
        body: JSON.stringify(user)
      })
        .then(res => res.json())
        .then(json => {
          console.log("password changed successfully!"+json)
          localStorage.setItem('changed',true)
          navigate('/login')
        }).catch(errors=>console.log(errors))
    }
  }

您需要像这样覆盖序列化程序的 update 方法:

class UserSerializer(serializers.ModelSerializer):

    class Meta:
        model = User
        fields='__all__' 

    def update(self, instance, validated_data):
        if 'password' in validated_data:
            password = validated_data.pop('password', None)
            instance.set_password(password)
        return super().update(instance, validated_data)