在Django Allauth中使用多个登录字段,电子邮件或电话号码

问题描述 投票:0回答:1

我正在使用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_USER_MODEL_USERNAME_FIELD ='phone_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',

)

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

django django-allauth django-custom-user
1个回答
0
投票

首先,你需要在django中为这样的电子邮件制作一个身份验证后端

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',
]

在之前的代码中,我假设您的身份验证后端位于帐户应用程序中名为身份验证的文件中

然后在视图中,您将验证用户身份然后登录

  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来简化操作

© www.soinside.com 2019 - 2024. All rights reserved.