通过扩展用户模式中的电话字段登录

2024-06-14 23:57:13 发布

您现在位置:Python中文网/ 问答频道 /正文

我使用了django用户模型,并对其进行了扩展,添加了一个phone字段。我可以使用用户名或电子邮件登录,但无法从扩展用户模型访问电话号码字段。你知道吗

你知道吗型号.py你知道吗

class Profile(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE)
    phonenumber = models.CharField(max_length=10)

你知道吗后端.py你知道吗

class AuthenticationBackend(backends.ModelBackend):
    def authenticate(self, request,  username=None, password=None, **kwargs):
        usermodel = get_user_model()
        print(usermodel)

        try:
            user = usermodel.objects.get(Q(username__iexact=username) | Q(
                email__iexact=username))
            if user.check_password(password):
                return user
        except user.DoesNotExist:
            pass

你知道吗后端.py是我用来实现通过用户名或电子邮件登录,但我不能在扩展用户模型的电话号码。你知道吗


Tags: 用户py模型nonegetmodelsusername电话号码
2条回答

您可以扩展AbstractUser并在其上添加电话号码。你知道吗

class User(AbstractUser):
    phonenumber = models.CharField(max_length=10)

    USERNAME_FIELD = 'phonenumber'

然后您应该在中指定自定义模型作为默认用户模型设置.py AUTH_USER_MODEL = 'app_name.User'

Customizing authentication in Django

有两种方法可以解决你的问题。你知道吗

  1. 通过子类化用户模型并更改默认用户模型来扩展用户模型。我建议你走这条路,因为电话号码是用来认证的。你知道吗
  2. 在Profile上设置相关的名称,并从该名称查询用户模型。你知道吗

对于第一个,我建议您查看Django documentation on creating custom users. 还有一个关于如何做到这一点的非常广泛的教程here。你知道吗

如果你想走简单的路线,你只需要在配置文件的phonenumber字段上设置一个反向访问器。你知道吗

class Profile(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE)
    phonenumber = models.CharField(max_length=10, related_name='profile')

然后,您可以按用户配置文件的电话号码搜索用户:

class AuthenticationBackend(backends.ModelBackend):
    def authenticate(self, request,  username=None, password=None, **kwargs):
        usermodel = get_user_model()
        print(usermodel)

        try:
            user = usermodel.objects.get(Q(username__iexact=username) | Q(
                email__iexact=username) | Q(profile__phonenumber__iexact=username)
            if user.check_password(password):
                return user
        except user.DoesNotExist:
            pass

虽然这不在您的问题范围内,但我认为您应该注意代码中的以下问题:

  • 电话号码通常比10个字符的字符串更复杂。+31612345678,是一个有效的电话号码,但超过10个字符。查看this question以获取有关如何存储和验证电话号码的指针。你知道吗
  • 如果使用字段进行身份验证,请确保它是唯一的。phonenumber字段实际上应该是phonenumber = models.CharField(max_length=10, related_name='profile', unique=True)
  • 如果存在电话号码为“0123456789”的用户和用户名为“0123456789”的其他用户,则您的usermodel.objects.get(...)查询将返回多个用户。您应该限制用户名不包含电话号码,这只能通过扩展默认用户类来实现。你知道吗

相关问题 更多 >