Home > other >  How to update password of Auth user in django rest framework
How to update password of Auth user in django rest framework

Time:04-16

I'm new to django rest framework. I'm implementing a simple login, signup and forgot password functionality using reactJs and django. All the functionalities are working fine but the problem I'm facing is that, on signup, the passwords in the database encrypted and then saved in the database but on updating password, the new password saved exactly same as user typed it. I want it also be encrypted in the database just like it encrypted in signup.

My serializer.py file

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

My views.py file

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)

        

This is the url I'm using for api

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

And this is how I called this api from reactjs

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

CodePudding user response:

You need to override serializer's update method like this:

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)
  • Related