通过电子邮件或移动电话号码在django中注册用户

Ale*_*cer 0 django django-models django-forms django-views

我有使用电子邮件作为身份验证的唯一标识符而不是用户名的自定义用户模型。我想通过电子邮件或手机号码注册用户。如果用户输入电子邮件地址,则通过激活链接注册用户;如果用户输入电话号码,则通过SMS OTP注册。

像instagram注册这样的东西:

https://www.instagram.com/accounts/emailsignup/

我找到了这个主题,但是答案却解释得不好。

Pwn*_*gns 6

username用户对象必需A。但是,您也可以使username它们email成为问题,所以这不是问题(至少在django 2.x中,不确定1.x左右)。您没有描述正在制作的应用程序的用途,用途等,因此在跳到代码之前,请阅读以下警告和有关我为什么会为您提供更好选择的思考过程。

强制该用户使用与电子邮件相同的用户名是一个非常糟糕的主意,因为将来您可能需要添加其他功能。

例如:也许您想制作一个留言板,以便人们可以互相交谈。但是由于从一开始就计划不周,每个人都会通过电子邮件看到对方。从技术上讲,您可以为他们分配一堆他们没有组成的随机用户名,但这不是一个好主意,因为他们不太可能记住它,并且他们可能不喜欢它。名称sPaRkLe_DaNcEr12或的唯一好用法Poothtaste是使人们在视频游戏中大发雷霆。

因此,如果您希望将来有能力让用户彼此交流,最好只向其他用户显示他们的用户名,但是如果愿意,则允许人们使用其电子邮件或电话号码登录。这样,他们现在可以使用登录(username) or (email) or (phone_number),而他们只需要记住其中一个即可。我会告诉你多久。

这有一些缺点:它对数据库进行更多查询,如果有大量用户,这可能会使数据库变慢,但这就是您的要求。我个人说这是值得的,因为它可以忽略不计,并且对于用户来说更容易,而且您应该迎合它们。因此,为更快的服务器付费,还是没有???最终,您总是应该围绕尽可能少的查询进行设计,同时缓存数据库中很繁重的某些页面,因此不必执行相同的操作X次。

让我们开始:

请记住,以下是我对django 2.x所做的示例,其功能比您要求的要好。如果您使用的是1.x,请使用url()代替path(),以及其他要求。

假设我们有一个名为的应用accounts_app

还要假设我们将path('accounts/', include('accounts_app.urls')),项目置于内部urls.py

我还将假设您知道如何使用模板...现在,urls.py在该应用程序内部创建一个:

account_app / urls.py:

app_name = 'accounts_app'

urlpatterns = [
    ...
    path('signup/', views.signup, name='signup'),
]
Run Code Online (Sandbox Code Playgroud)

account_app / models.py:

user下面的属性使您可以扩展User模型,因此也可以使用它们phone_number。在此示例中,我允许将其保留为空白,以防万一他们不想给它。但是,如果这样做了,您将对此有不同的看法。为了使整个过程变得更加简单,我将不包括在内,也不会告诉您如何覆盖整个User模型。我仅向您展示如何使用常规User模型通过电子邮件登录。在那之后,使用电话号码这样做根本不难。这篇文章的结尾提醒您需要什么。

class ExtendedUserExample(models.Model):
    user = models.OneToOneField(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
    created = models.DateTimeField(auto_now_add=True)
    phone_number = models.IntegerField(blank=True)
Run Code Online (Sandbox Code Playgroud)

settings.py...。请注意,这在项目文件夹中

这些后端的顺序很重要。请始终先执行ModelBackend,否则它将损坏。

AUTHENTICATION_BACKENDS = [
    'django.contrib.auth.backends.ModelBackend',
    'accounts_app.authentication.EmailAuthBackend',  # to be able to login with email, described next
]
Run Code Online (Sandbox Code Playgroud)

account_app / authentication.py:

这是一个能够通过他们的电子邮件登录的示例。如果您也希望某人也通过其电话号码登录,则原理是相同的,但是在此文件中,您还需要导入ExtendedUserExample上面的模型,将其添加到AUTHENTICATION_BACKENDS其底部的上述设置中,然后新建一个类对PhoneAuthBackend,那搜索ExtendedUserExamplephone_number。再次,为了简化操作,我并没有完全覆盖User模型,而只是扩展了模型,因此,如果用户注册了一个帐户并希望以后通过电话号码登录,则他们必须使用用户名和电子邮件进行注册。首先,进入后,他们可以添加电话号码(在此示例中,您将需要另一个视图)。

因此,请先尝试使用此电子邮件示例,直到掌握了它。您也不需要在其他任何地方导入该文件,因为该settings.py文件可以处理该文件。

这是发生的情况:在用于登录的模板上,它将首先usernameUser模型内部搜索字段,因为settings.py文件中的AUTHENTICATION_BACKENDS变量ModelBackend首先要检查。

但是,假设一个用户输入他们的username作为aaa@aaa.com。现在,由于您不允许任何人使用电子邮件作为用户名进行注册,aaa@aaa.com因此usernameUser模型中找不到时,您的设置文件现在说User第二遍检查同一对象,但可以通过email字段搜索他们的输入/列代替。如果在该列中存在他们的输入,authenticate()则在密码正确的情况下通过他们的电子邮件登录。

from django.contrib.auth.models import User

class EmailAuthBackend(object):
    """ Authenticate using an email address """

    def authenticate(self, request, username=None, password=None):
        try:
            user = User.objects.get(email=username)  # gets the email by the 'username' they entered
            if user.check_password(password):
                return user
            return None
        except User.DoesNotExist:
            return None

    def get_user(self, user_id):
        try:
            return User.objects.get(pk=user_id)
        except User.DoesNotExist:
            return None
Run Code Online (Sandbox Code Playgroud)

acounts_app / views.py:

我假设您知道如何制作Django表格。如果不是,请在此处查看模型表格。

from .forms import ExtendedUserForm

def signup(request):
    form = ExtendedUserForm(request.POST or None)
    if request.method == 'POST':
        if request.POST['password1'] == request.POST['password2']:
            potential_user = request.POST.get('username', False).lower()
            try:
                user = User.objects.get(username=potential_user)
                return render(request, 'accounts_app/signup.html', {'error': 'Username has already been taken. Please try another'})
            except User.DoesNotExist:
                if form.is_valid():
                    new_user = User.objects.create_user(username=potential_user, email=request.POST['email'], password=request.POST['password1'])

                    # backend argument required cause we are making the ability to LOGIN by email.
                    # Remember, I only extended the User model.
                    auth.login(request, new_user, backend='django.contrib.auth.backends.ModelBackend')

                    return redirect('some_app:some_view')
        else:
            return render(request, 'accounts_app/signup.html', {'error': "Password's must match."})
    return render(request, 'accounts_app/signup.html', {'form': form})
Run Code Online (Sandbox Code Playgroud)

现在您应该可以通过电子邮件登录,因此遵循这些原则创建相同的电话登录功能并不困难。如果继续此示例,则需要创建新视图以将电话号码保存到ExtendedUserExample.phone_number。之后,在的底部添加另一行,在中AUTHENTICATION_BACKENDS编写一个新类authentication.py,您将被设置为...,只要<input type="text" name="username" required>他们使用登录视图即可。