Django实战之用户登录

对与Django认证系统使用默认的auth就可以了,但默认的有时无法满足我们的业务需求,需要额外的定制才能满足,例如用户表,默认情况下是没有手机号,昵称,头像这些字段的,那如果我需要,怎么办?还有我们认证也仅支持用户名与密码,如果我想认证可以实现用户名或者邮箱或者手机号+密码方式认证呢?

今天我就要来解决下面的2个问题.
1) 原先的user表字段
(username,password,first_name,last_name,email,last_login,is_superuser,is_staff,is_active,date_joined),仅有这10个,因我也需要记录用户手机号(可能还需要记录用户昵称,头像等,此案例中我仅扩展一个手机号字段,若添加其它字段则和此手机号字段一样),所以暂时看起来无法满足现在的需求,所以我们需要重新定义user表.
2) 原先的认证,仅支持用户名+密码,现在我们需要实现(用户名或邮箱或手机号)+密码这种方式认证登录.

下面开始动手做起来.
1) 启动一个user应用startapp user
2) 定义一个UserProfile表
user.models.models

from django.contrib.auth.models import AbstractUser

# Create your models here.

class UserProfile(AbstractUser):
    mobile = models.CharField(max_length=11,
                              verbose_name="手机号",
                              unique=True,
                              error_messages={
                                  'unique': "此手机号已经存在."
                              }
                              )

    class Meta:
        verbose_name = "用户信息"
        verbose_name_plural = verbose_name

    def __str__(self):
        return self.username

3) settings.py中设置
3.1应用相关配置
INSTALLED_APPS = [
…………
'user.apps.UserConfig',
]
3.2 mysql数据库驱动
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': "bookops",
'USER': 'root',
'PASSWORD': "root",
'HOST': "127.0.0.1",
"OPTIONS": {"init_command": "SET default_storage_engine=INNODB;"}
}
3.3 定义扩展的Auth表
"""
认证相关
"""
AUTH_USER_MODEL = 'user.UserProfile'

3.4 定义一个静态文件路径,将css/js/image放与此目录下.
STATIC_URL = '/static/'
STATICFILES_DIRS = (
os.path.join(BASE_DIR, "static"),
)
4) 接下来去创建相应的表
makemigrations
migrate
查看mysql数据库,有相应的表与mobile字段.
Django实战之用户登录
5) 设置一个超级用户,用与登录验证.
manage.py@django_edu > createsuperuser
...
Username: opdevos
Email address: [email protected]
Warning: Password input may be echoed.
Password: admin123
Warning: Password input may be echoed.
Password (again): admin123
Superuser created successfully.

设置了一个用户名为opdevos密码admin123,邮箱[email protected].下面到数据库里设置一个11位的手机号.
Django实战之用户登录
好了,数据准备工作做好了。我们就去写相关的逻辑程序与前台显示页面吧.
urls.py
from user.views import index, login, logout
urlpatterns = [
...
url(r'^index/', index),
url(r'^login/', login),
url(r'^logout/', logout),
...
]

views.py

from django.shortcuts import render , redirect

from django.contrib import auth

# Create your views here.

from django.contrib.auth.backends import ModelBackend
from .models import UserProfile

# 并集运算
from django.db.models import Q

# 实现用户名邮箱手机号均可登录
# 继承ModelBackend类,因为它有方法authenticate,可点进源码查看
class CustomBackend(ModelBackend):
    def authenticate(self, request, username=None, password=None, **kwargs):
        try:
            # 不希望用户存在两个,get只能有一个。两个是get失败的一种原因 Q为使用并集查询

            user = UserProfile.objects.get(Q(username=username)|Q(email=username)|Q(mobile=username))

            # django的后台中密码加密:所以不能password==password
            # UserProfile继承的AbstractUser中有def check_password(self, raw_password):

            if user.check_password(password):
                return user
        except Exception as e:
            return None

def index(request):
    return render(request,"index.html")

def login(request):

    # 登录提交表单为post
    if request.method == "POST":
        # 取不到时为空,username,password为前端页面name值
        user_name = request.POST.get("username", "")
        pass_word = request.POST.get("password", "")

        # 成功返回user对象,失败返回null
        user = auth.authenticate(username=user_name, password=pass_word)

        # 如果不是null说明验证成功
        if user is not None:
            # login 两参数:request, user
            # 实际是对request写了一部分东西进去,这一部分东西其实就是服务端会生成一个sessionID,
            # 和其对应的用户相关数据信息,将其sessionID与用户相关数据写到数据库中,
            # 并且将sessionID写到request的cookie中,后期浏览器再发送请求,便将此sessionID发送到Django中,
            #Django的session中间件再将其获取,并解析出用户user对象赋值给request.user
            auth.login(request, user)
            # 跳转到首页 user request会被带回到首页
            return redirect("/index/")
    return render(request, "login.html", {})

def logout(request):
    auth.logout(request)
return redirect("/login/")

此时需要在settings.py中设置自定义的认证.
"""
认证相关
"""
AUTH_USER_MODEL = 'user.UserProfile'

#设置邮箱或手机号或用户名均可登录
AUTHENTICATION_BACKENDS = (
'user.views.CustomBackend',
)

login.html

login.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>用户登录</title>
    <link rel="stylesheet" href="/static/bootstrap/css/bootstrap.css">
</head>
<body>

<div class="container">
    <div class="row">
        <div class="col-md-6 col-md-offset-3">

            <div class="page-header">
                <h1>用户登录
                    <small>Access Login</small>
                </h1>
            </div>
            <form action="" method="POST" class="form-horizontal">
                {% csrf_token %}
                <div class="form-group">
                    <label for="username" class="col-sm-2 control-label">UserName</label>
                    <div class="col-sm-10">
                        <input type="text" class="form-control" name="username" placeholder="用户名|邮箱|手机号">
                    </div>
                </div>
                <div class="form-group">
                    <label for="password" class="col-sm-2 control-label">Password</label>
                    <div class="col-sm-10">
                        <input type="password" class="form-control" name="password" placeholder="Password">
                    </div>
                </div>
                <div class="form-group">
                    <div class="col-sm-offset-2 col-sm-10">
                        <div class="checkbox">
                            <label>
                                <input type="checkbox"> Remember me
                            </label>
                        </div>
                    </div>
                </div>
                <div class="form-group">
                    <div class="col-sm-offset-2 col-sm-10">
                        <button type="submit" class="btn btn-default">Sign in</button>
                    </div>
                </div>
            </form>

        </div>
    </div>
</div>

</body>
</html>

index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Index</title>
</head>
<body>
{{ request.user.username }}
<a href="/logout">退出</a>
</body>
</html>

以下是验证相关图片.
访问
Django实战之用户登录
输入用户名+密码
Django实战之用户登录

Django实战之用户登录

退出,再用邮箱+密码登录.
Django实战之用户登录

Django实战之用户登录
退出,再用手机号+密码登录.
Django实战之用户登录

Django实战之用户登录

哈哈。看到没,三种登录方式都已经成功了.
对与数据检验,我这里没有去做,不过,可以在我下一篇实战用户注册这块来弥补.

如果想了解更多,请关注我们的公众号
公众号ID:opdevos
扫码关注
Django实战之用户登录

猜你喜欢

转载自blog.51cto.com/5ydycm/2342179