在Django All Auth中使用多个登录字段、电子邮件或电话号码

在Django All Auth中使用多个登录字段、电子邮件或电话号码,django,django-allauth,django-custom-user,Django,Django Allauth,Django Custom User,我正在使用Django All Auth对用户进行身份验证,但我需要在登录用户时使用电话号码或电子邮件字段。我将用户类扩展如下: class User(AbstractUser): phone_number = models.CharField(max_length=10, unique=True) def __unicode__(self): return self.username 我的注册表格如下所示: class SignupForm(forms.

我正在使用Django All Auth对用户进行身份验证,但我需要在登录用户时使用电话号码或电子邮件字段。我将用户类扩展如下:

class User(AbstractUser):
    phone_number = models.CharField(max_length=10, unique=True)


    def __unicode__(self):
        return self.username 
我的注册表格如下所示:

class SignupForm(forms.Form):
    phone_number = forms.CharField(max_length=10,label='phone_number')

    def signup(self, request, user):
        user.phone_number = self.cleaned_data['phone_number']
        user.save()
电话号码保存在后端使用这个,但我需要验证用户,如果他输入电子邮件或电话号码。Django All Auth需要扩展什么类。我读了很多问题,但没有找到好的

如果我在settings.py中放置ACCOUNT\u USER\u MODEL\u USERNAME\u FIELD='phone\u number',它将通过电话而不是电子邮件进行身份验证

编辑1:

我创建了一个backends.py文件,并编写了以下代码

class PhoneNumberBackend(object):
    """
    Custom Phone Number Backend to perform authentication via phone number
    """
    def authenticate(self, username=None, password=None):
        my_user_model = get_user_model()

        try:
            user = my_user_model.objects.get(phone_number=username)
            if user.check_password(password):
                return user # return user on valid credentials
        except my_user_model.DoesNotExist:
            return None # return None if custom user model does not exist 
        except:
            return None # return None in case of other exceptions

    def get_user(self, user_id):
        my_user_model = get_user_model()
        try:
            return my_user_model.objects.get(pk=user_id)
        except my_user_model.DoesNotExist:
            return None
Settings.py现在看起来像这样:

AUTHENTICATION_BACKENDS = (
    # 'userauth.backends.PhoneNumberBackend',
    # Needed to login by username in Django admin, regardless of `allauth`
    'django.contrib.auth.backends.ModelBackend',

    # `allauth` specific authentication methods, such as login by e-mail
    'allauth.account.auth_backends.AuthenticationBackend',

)

它应该使用电话号码进行身份验证,如果没有,则返回到其他身份验证方法,对吗?它不是那样工作的。

首先,您需要在djagno中创建一个身份验证后端 像这样的电子邮件

class EmailAuthentication(object):
def authenticate(self, request, username=None, password=None):
    try:
        user = User.objects.get(email=username)
        if user.check_password(password):
            return user
        return None
    except:
        return None
def get_user(self, user_id):
    try:
        return User.objects.get(id=user_id)
    except:
return None
def clean_email(self):
    email = self.cleaned_data['email']
    if User.objects.filter(email=email).exists():
        raise forms.ValidationError(' user with this email is already registered -- Try loginigin or resting the password')    
    return email
你可以为电话号码再做一个 但要确保它们在数据库中是唯一的,这样就没有人必须使用相同的凭据访问帐户 你可以用像这样的方法检查它 这也是电子邮件

class EmailAuthentication(object):
def authenticate(self, request, username=None, password=None):
    try:
        user = User.objects.get(email=username)
        if user.check_password(password):
            return user
        return None
    except:
        return None
def get_user(self, user_id):
    try:
        return User.objects.get(id=user_id)
    except:
return None
def clean_email(self):
    email = self.cleaned_data['email']
    if User.objects.filter(email=email).exists():
        raise forms.ValidationError(' user with this email is already registered -- Try loginigin or resting the password')    
    return email
然后,您应该将auth后端放在设置文件中,不要忘记包括django的原始用户名后端

AUTHENTICATION_BACKENDS = [
'django.contrib.auth.backends.ModelBackend',
'account.authentication.EmailAuthentication',
]
在前面的代码中,我假设您的身份验证后端位于帐户应用程序中名为authentication的文件中

然后在视图中,您将对用户进行身份验证,然后让他登录

  username = form.cleaned_data['username']
  password = form.cleaned_data['password2']
  user = authenticate(username=username, password=password)
  if user:
      login(request, user)

或者,您可以使用django.contrib.auth.views中的LoginView使其更简单

首先,您需要在djagno中创建一个身份验证后端 像这样的电子邮件

class EmailAuthentication(object):
def authenticate(self, request, username=None, password=None):
    try:
        user = User.objects.get(email=username)
        if user.check_password(password):
            return user
        return None
    except:
        return None
def get_user(self, user_id):
    try:
        return User.objects.get(id=user_id)
    except:
return None
def clean_email(self):
    email = self.cleaned_data['email']
    if User.objects.filter(email=email).exists():
        raise forms.ValidationError(' user with this email is already registered -- Try loginigin or resting the password')    
    return email
你可以为电话号码再做一个 但要确保它们在数据库中是唯一的,这样就没有人必须使用相同的凭据访问帐户 你可以用像这样的方法检查它 这也是电子邮件

class EmailAuthentication(object):
def authenticate(self, request, username=None, password=None):
    try:
        user = User.objects.get(email=username)
        if user.check_password(password):
            return user
        return None
    except:
        return None
def get_user(self, user_id):
    try:
        return User.objects.get(id=user_id)
    except:
return None
def clean_email(self):
    email = self.cleaned_data['email']
    if User.objects.filter(email=email).exists():
        raise forms.ValidationError(' user with this email is already registered -- Try loginigin or resting the password')    
    return email
然后,您应该将auth后端放在设置文件中,不要忘记包括django的原始用户名后端

AUTHENTICATION_BACKENDS = [
'django.contrib.auth.backends.ModelBackend',
'account.authentication.EmailAuthentication',
]
在前面的代码中,我假设您的身份验证后端位于帐户应用程序中名为authentication的文件中

然后在视图中,您将对用户进行身份验证,然后让他登录

  username = form.cleaned_data['username']
  password = form.cleaned_data['password2']
  user = authenticate(username=username, password=password)
  if user:
      login(request, user)

或者您也可以使用django.contrib.auth.views中的LoginView使其更简单

我以前也做过类似的事情。我认为您应该子类化
BaseUserManager
类,并通过一些调整定义您自己的自定义用户管理器。但是django all-auth settings ACCOUNT\u AUTHENTICATION\u方法仍然适用,即使我们使用BaseUserManager。没有?我以前也做过类似的事情。我认为您应该子类化
BaseUserManager
类,并通过一些调整定义您自己的自定义用户管理器。但是django all-auth settings ACCOUNT\u AUTHENTICATION\u方法仍然适用,即使我们使用BaseUserManager。否?因为我正在使用Django All Auth,所以它已经有AuthenticationBackend,我们应该能够以某种方式扩展它,以允许电话号码或任何其他字段作为登录名。我已经为手机制作了另一个后端,但仍然不知道这是不是正确的方法。你可以通过这种方式扩展它,让自己放心,这种方式来自django2by示例书,我对它进行了一些修改,当你把auth后端放在设置上时,django会尝试连续地对每个用户进行身份验证,如果它找到一个知道用户的auth,它将停止,我认为如果相同的结果将返回相同的结果,则无需进行两次异常,如果您愿意,您可以在github上共享代码,这样我就可以编辑代码或查看整个身份验证周期,我不擅长给出正确的假设,因为我还不在git上。我能说的是,使用的登录视图是allauth的默认视图,或者您认为我需要覆盖它?因为我使用Django All Auth,所以它已经有AuthenticationBackend,我们应该能够以某种方式扩展它,以允许电话号码或任何其他字段作为登录。我已经为手机制作了另一个后端,但仍然不知道这是不是正确的方法。你可以通过这种方式扩展它,让自己放心,这种方式来自django2by示例书,我对它进行了一些修改,当你把auth后端放在设置上时,django会尝试连续地对每个用户进行身份验证,如果它找到一个知道用户的auth,它将停止,我认为如果相同的结果将返回相同的结果,则无需进行两次异常,如果您愿意,您可以在github上共享代码,这样我就可以编辑代码或查看整个身份验证周期,我不擅长给出正确的假设,因为我还不在git上。我能说的是,正在使用的登录视图是allauth的默认视图,或者您认为我需要覆盖它?