1. 程式人生 > >Django實戰之使用者登入

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) 設定一個超級使用者,用與登入驗證.
[email protected]_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實戰之使用者登入