Amir Rezazadeh
Amir Rezazadeh

Reputation: 99

Django get_user_model().objects.create() password is not getting hashed

I have a test case which first creates a user and then try's to authenticate the created user with Django authenticate() method but looks like password is not getting hashed and therefore it fails to retrieve the token... ill share any code related to this section that i think had to do something with the process.

Custom user model manager:

class UserManager(BaseUserManager):

def create_user(self, email, password=None, **extra_fields):
    """ Creates and saves a new user """

    if not email:
        raise ValueError("Users must have an email address.")

    user = self.model(
        email=self.normalize_email(email),
        **extra_fields
    )

    # Set password this way makes a hashed password
    user.set_password(password)
    user.save(using=self._db)

    return user

app/settings.py:

AUTH_USER_MODEL = "core.User" # 'User' is the name of custom user class

user/serializers.py:

class UserSerializer(serializers.ModelSerializer):
    """ Serializer for the users object """

    class Meta:
        model = get_user_model()
        fields = ["email", "password", "name"]
        extra_kwargs = {
            "password": {
                "write_only": True,
                "min_length": 5,
            }
        }

    def create(self, validated_data):
        """ Create a new user with encrypted password and return it """
        user = get_user_model().objects.create(
            email=validated_data["email"],
            name=validated_data["name"]
        )
        user.set_password(validated_data["password"])
        print(f"from serializer: {user.password}")
        user.save()

        return user

and at last my test case, user/tests/test_user.py:

  #...
  def test_create_token_for_user(self):
        """ Test that a token is created for the user """
        payload = {
            "email": "[email protected]",
            "password": "testpass"
        }
        user = get_user_model().objects.create(**payload)

        print(user.password) # returns 'testpass' in plain text...

        res = self.client.post(TOKEN_URL, payload)

        self.assertIn("token", res.data)
        self.assertEqual(res.status_code, status.HTTP_200_OK)

Upvotes: 1

Views: 967

Answers (1)

willeM_ Van Onsem
willeM_ Van Onsem

Reputation: 476503

You should use create_user in the test, so:

def test_create_token_for_user(self):
    payload = {
        'email': '[email protected]',
        'password': 'testpass'
    }
    #                     use create_user ↓
    user = get_user_model().objects.create_user(**payload)

    print(user.password)
    res = self.client.post(TOKEN_URL, payload)

    self.assertIn('token', res.data)
    self.assertEqual(res.status_code, status.HTTP_200_OK)

In the serializer you can also work with .create_user():

class UserSerializer(serializers.ModelSerializer):
    # …

    def create(self, validated_data):
        user = get_user_model().objects.create_user(
            email=validated_data['email'],
            name=validated_data['name'],
            password=validated_data['password']
        )
        return user

Upvotes: 2

Related Questions