how to mention password field in serializer?

13,086

Solution 1

to hash password, call:

make_password(origin_password)

example serializers.py:

from rest_framework import serializers
from django.contrib.auth.models import User
from django.contrib.auth.hashers import make_password


class UserSerializer(serializers.HyperlinkedModelSerializer):

    password = serializers.CharField(
        write_only=True,
        required=True,
        help_text='Leave empty if no change needed',
        style={'input_type': 'password', 'placeholder': 'Password'}
    )

    class Meta:
        model = User
        fields = ('url', 'username', 'email', 'password')

    def create(self, validated_data):
        validated_data['password'] = make_password(validated_data.get('password'))
        return super(UserSerializer, self).create(validated_data)

Solution 2

Change serializers.py as below

class UserSerializer(serializers.ModelSerializer):
    password = serializers.CharField(write_only=True)

    class Meta:
        model = User
        fields = ('username', 'email', 'password', 'firstname', 'last name')

    def create(self, validated_data):
        user = super().create(validated_data)
        user.set_password(validated_data['password'])
        user.save()
        return user

    def update(self, instance, validated_data):
        user = super().update(instance, validated_data)
        try:
            user.set_password(validated_data['password'])
            user.save()
        except KeyError:
            pass
        return user

Solution 3

There was no special field for password in DRF. In my current project we used to define password field as CharField with write_only=True inside serializer class.

Solution 4

The @MahdiSorkhmiri answer is working perfectly for me. Here is how my file is looking write now.

   class UserSerializer(serializers.ModelSerializer):
        email = serializers.EmailField(
        validators=[UniqueValidator(UserModel.objects.all())]
        )
        password = serializers.CharField(
        min_length=4,
        write_only=True,
        required=True,
        style={'input_type': 'password'}
        )
    def create(self, validated_data):
        fields = ['username', 'password', 'email']
        data = {f: validated_data.get(f) for f in fields}

        return UserModel.objects.create_user(**data)

    class Meta:
        model = UserModel
        fields = 'username email last_name first_name password'.split()
Share:
13,086
Mahdi Sorkhmiri
Author by

Mahdi Sorkhmiri

Back-end developer with years of experience in developing high-quality code on top of different technology stacks and with different architectures. interested in hardware and IoT.

Updated on July 21, 2022

Comments

  • Mahdi Sorkhmiri
    Mahdi Sorkhmiri almost 2 years

    I have a custom user for authentication and want to create a serializer class for it my custom user's model is like this :

    class User (AbstractUser):
            bio = models.TextField(max_length=500, blank=True)
            birth_date = models.DateField(null=True, blank=True)
            image=models.FileField(null=True , blank=True)
    

    and my serializer is :

    class UserSerializer (serializers.ModelSerializer):
        class Meta:
            model = User
            fields = ('username' ,'email' ,'password' ,'firstname' , 'last name' )
    

    how could I mention that the password field is a password and its content must be hashed?

  • Mahdi Sorkhmiri
    Mahdi Sorkhmiri about 6 years
    this code you added hides the password field in getting request but it's still not hashed and look like a normal text
  • JPG
    JPG about 6 years
    Did your password not hashed? Can you add your current response as screenshot or something ?
  • Shubho Shaha
    Shubho Shaha about 6 years
    Something like this password = serializers.CharField(max_length=128, write_only=True, required=True)
  • Aman Sharma
    Aman Sharma almost 6 years
    @MahdiSorkhmiri, I don't know how to hash it but to hide the text you can wirte it like this: password = serializers.CharField(write_only=True, style={'input_type': 'password'})
  • help-info.de
    help-info.de about 5 years
    Welcome to Stack Overflow! Here is a guide on How to Answer. Please don't add "thanks" as answers. They don't actually provide an answer to the question, and can be perceived as noise by its future visitors. Once you earn enough reputation, you will gain privileges to upvote answers you like. This way future visitors of the question will see a higher vote count on that answer, and the answerer will also be rewarded with reputation points. See Why is voting important.
  • Oli
    Oli over 4 years
    This will write the raw password directly into the database, rather than hashing it via user.set_password (which itself uses make_password). Making it write_only is only half the job.
  • JPG
    JPG over 4 years
    @Oli Yeah..you were right. Thanks for the correction and I have updated the answer :)
  • Evren Bingøl
    Evren Bingøl over 3 years
    you need to call make_password to hash
  • Enzo Dtz
    Enzo Dtz almost 3 years
    with this it keep showing on OPT request, but not on GET ones. perfect! thanks
  • Elias Prado
    Elias Prado almost 3 years
    Just to remmember that set_password() is only for User model. For those who are looking to hash not User password you should use make_password method from auth.hashers.
  • Elias Prado
    Elias Prado almost 3 years
    The greater of this approach is that the make_password method can also be used for not User serialzer method too. Thank you for your answer.