【问题标题】:Django get_user_model().objects.create() password is not getting hashedDjango get_user_model().objects.create() 密码没有得到散列
【发布时间】:2021-04-15 09:57:03
【问题描述】:

我有一个测试用例,它首先创建一个用户,然后尝试使用 Django authenticate() 方法对创建的用户进行身份验证,但看起来密码没有得到散列,因此无法检索令牌...我将分享与本节相关的任何代码,我认为这些代码必须对流程进行处理。

自定义用户模型管理器

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

用户/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

最后是我的测试用例 user/tests/test_user.py:

  #...
  def test_create_token_for_user(self):
        """ Test that a token is created for the user """
        payload = {
            "email": "test@test.com",
            "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)

【问题讨论】:

    标签: python django django-models django-rest-framework tdd


    【解决方案1】:

    你应该在测试中使用create_user,所以:

    def test_create_token_for_user(self):
        payload = {
            'email': 'test@test.com',
            '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)

    在序列化程序中,您还可以使用.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

    【讨论】:

    • 完全正确,非常感谢。我在序列化程序和管理器中都使用了 user.set_password() 的另一个问题。这是错误的还是将来可能会导致任何问题?
    • @AmirRezazadeh:我会在序列化程序中使用.create_user,从而将密码传递给序列化程序。这更有意义,因为它避免了代码重复
    • 对不起,我很困惑,你的意思是在序列化程序类中使用 .create_user ?我以为序列化程序类中只有 .create() ......
    猜你喜欢
    • 2020-11-09
    • 1970-01-01
    • 1970-01-01
    • 2022-01-06
    • 2013-03-09
    • 2016-02-13
    • 2022-12-19
    • 2018-10-14
    • 2023-03-07
    相关资源
    最近更新 更多