【问题标题】:Django authenticate() always return None for a custom modelDjango authenticate() 总是为自定义模型返回 None
【发布时间】:2019-07-29 14:02:08
【问题描述】:

我是 django 的新手,我必须用它做一个后端。 我的问题:我有多个模型(客户、司机、公司),它们都应该登录并进行身份验证(每个都在不同的应用程序上,但它们都扩展了相同的用户模型),我见过很多这样的问题,但没有其中解决了我的问题,即 authenticate(username='username',password='password') 总是不返回任何内容。 用户记录存在于数据库中,我用 filter(username=(username). 所以这里有一些代码:

UserManager 类:

class UserManager(BaseUserManager):

def create_user(self, username, password, phone):
    if not username:
        raise ValueError("user must provide a username")
    if not password:
        raise ValueError("user must provide a password")
    if not phone:
        raise ValueError("user must povide a phone number")

    user_obj = self.model(
        user_name=username,
        phone=phone
    )
    user_obj.set_password(password)
    user_obj.save()
    return user_obj

用户类:

class User(AbstractBaseUser):
    user_name = models.CharField(max_length=32, unique=True)
    email = models.EmailField(max_length=255, unique=True, null=True)
    phone = PhoneNumberField()
    access_token = models.CharField(max_length=255, unique=True, null=True)
    notifications_token = models.CharField(max_length=255, unique=True, null=True)
    photo = models.ImageField()
    person_in_contact = models.CharField(max_length=32)
    active = models.BooleanField(default=False)
    confirmedEmail = models.BooleanField(default=False)
    confirmedPhone = models.BooleanField(default=False)
    completedProfile = models.BooleanField(default=False)

    objects = UserManager()

    @property
    def is_active(self):
        return self.active

    def __str__(self):
        return "Client : " + self.user_name + " Email:" + self.email

    def get_email(self):
        return self.email

    USERNAME_FIELD = 'user_name'

    REQUIRED_FIELDS = ['username', 'phone', 'password']

    class Meta:
        abstract = True

Person 类(客户端和驱动程序由此扩展):

class Person(User):
    GENDER = (('F', 'FEMALE'), ('M', 'MALE'))

    name = models.CharField(max_length=50, null=True)
    surname = models.CharField(max_length=50, null=True)
    adress = models.CharField(max_length=255, null=True)
    birth_date = models.DateField(null=True)
    gender = models.CharField(max_length=1, choices=GENDER, default='M')

    def age(self):
        today = date.today()
        return today.year - self.birth_date.year

    def __str__(self):
        return super().__str__() + " Name : " + self.name

    class Meta:
        abstract = True

这是我正在测试的驱动程序模型(如果成功,我将对其他 2 个模型应用相同的方法):

class Driver(Person):
    rating = models.DecimalField(default=0, decimal_places=1, max_digits=3)
    driving_license = models.CharField(max_length=50, null=True)
    insurance_number = models.CharField(max_length=50, null=True)
    company = models.ForeignKey(TransportCompany, on_delete=models.DO_NOTHING, null=True)

我的 settings.py 文件夹已设置:

AUTHENTICATION_BACKENDS = (
'django.contrib.auth.backends.ModelBackend',
)

AUTH_USER_MODEL = 'drivers.Driver'

这是我在 python 控制台中的测试方式:

>>> from django.contrib.auth import authenticate
>>> print (authenticate(username='Simouchee',password='123456789'))
None

当我使用过滤器测试并存在时:

>>> driver = Driver.objects.filter(user_name = 'Simouchee')
>>> driver.exists()
True

感谢任何有关如何正确验证自定义模型的帮助/提示。 真的很抱歉,我觉得需要详细解释的长线程。

【问题讨论】:

  • 如果检索实例,driver.check_password('123456789') 是否返回True
  • 在运行身份验证之前如何在控制台中创建驱动程序?
  • @schwobaseggl 是的,它确实返回 true。
  • @Hanny 我没有在控制台中创建驱动程序,驱动程序已经在数据库中,我只是在尝试对其进行身份验证。
  • 为什么不只创建一个测试(自动) - 然后创建用户并在测试中查找/诊断问题,而不是使用数据库中可能发生变化的数据?然后您可以创建用户并尝试进行身份验证以确保 100% 它与可能导致某些问题的数据无关?这是更安全的方式,自动化并确保您一直负责该过程 - 而且,它可以在未来为其他用户重现,可在任何地方进行测试,并允许您测试您的代码以应对未来的变化,所以你知道它不会坏。

标签: python django


【解决方案1】:

你这里有一个错误authenticate(username='Simouchee',password='123456789')

您的模型中有user_name,但authenticate 调用中有username

我想说,最好在模型中使用不带下划线的 username,就像在 django 框架本身中一样 - https://github.com/django/django/blob/master/django/contrib/auth/models.py#L299

还要检查这里提到的密码 - Django authenticate() always return None for a custom model

已编辑:问题可能在 User 模型中。您有 default=False 字段 active,因此还要检查您的用户是否处于活动状态。由于ModelBackend 在方法user_can_authenticate 中检查is_active - https://github.com/django/django/blob/master/django/contrib/auth/backends.py#L51

【讨论】:

  • 默认的ModelBackend 将传递给authenticate 的标准username kwarg 转换为USERNAME_FIELD 上的查询(参见github.com/django/django/blob/master/django/contrib/auth/…)。所以下划线应该不是问题。
  • @schwobaseggl 是对的,我按照你说的做了,但还是同样的问题。
  • @schwobaseggl,这是真的,我的错。好吧,由于您的链接,我还有一个猜测。 @wassimchaguetmi,请检查您的用户是否处于活动状态。你有default=False 字段active
  • 天哪,兄弟,你太棒了,它成功了!我以为我必须自己检查是否处于活动状态,我不知道 django 会自动为我做这件事。我所要做的就是让用户在数据库中明确地处于活动状态,并且它正确地进行了身份验证并返回了用户。非常感谢您,编辑您的答案,以便我可以接受,以便其他人可以从中受益。
【解决方案2】:

听起来您的代码没有问题。 Django内置的Authenticate功能完美运行,请确保用户创建正确。

如果您使用它来创建用户:

user = User.objects.create(username=username, password=user_password, email=user_email)

它将创建用户,但它可能无法进行身份验证。它会返回 None,它也发生在我身上。

请试试这个:

user = User.objects.create_user(username=username, password=user_password, email=user_email) 用户.save()

然后尝试验证(用户名=用户名,密码=密码) 它应该工作!

【讨论】:

    猜你喜欢
    • 2015-12-21
    • 1970-01-01
    • 2020-07-09
    • 2016-07-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-09-10
    相关资源
    最近更新 更多