對與Django認證系統使用默認的auth就能夠了,但默認的有時沒法知足咱們的業務需求,須要額外的定製才能知足,例如用戶表,默認狀況下是沒有手機號,暱稱,頭像這些字段的,那若是我須要,怎麼辦?還有咱們認證也僅支持用戶名與密碼,若是我想認證能夠實現用戶名或者郵箱或者手機號+密碼方式認證呢?css
今天我就要來解決下面的2個問題.
1) 原先的user表字段
(username,password,first_name,last_name,email,last_login,is_superuser,is_staff,is_active,date_joined),僅有這10個,因我也須要記錄用戶手機號(可能還須要記錄用戶暱稱,頭像等,此案例中我僅擴展一個手機號字段,若添加其它字段則和此手機號字段同樣),因此暫時看起來沒法知足如今的需求,因此咱們須要從新定義user表.
2) 原先的認證,僅支持用戶名+密碼,如今咱們須要實現(用戶名或郵箱或手機號)+密碼這種方式認證登陸.html
下面開始動手作起來.
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'mysql
3.4 定義一個靜態文件路徑,將css/js/image放與此目錄下.
STATIC_URL = '/static/'
STATICFILES_DIRS = (
os.path.join(BASE_DIR, "static"),
)
4) 接下來去建立相應的表
makemigrations
migrate
查看mysql數據庫,有相應的表與mobile字段.
5) 設置一個超級用戶,用與登陸驗證.
manage.py@django_edu > createsuperuser
...
Username: opdevos
Email address: opdevos@opdevos.com
Warning: Password input may be echoed.
Password: admin123
Warning: Password input may be echoed.
Password (again): admin123
Superuser created successfully.sql
設置了一個用戶名爲opdevos密碼admin123,郵箱opdevos@opdevos.com.下面到數據庫裏設置一個11位的手機號.
好了,數據準備工做作好了。咱們就去寫相關的邏輯程序與前臺顯示頁面吧.
urls.py
from user.views import index, login, logout
urlpatterns = [
...
url(r'^index/', index),
url(r'^login/', login),
url(r'^logout/', logout),
...
]數據庫
views.pydjango
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'bootstrap
#設置郵箱或手機號或用戶名都可登陸
AUTHENTICATION_BACKENDS = (
'user.views.CustomBackend',
)瀏覽器
login.htmlcookie
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>
如下是驗證相關圖片.
訪問
輸入用戶名+密碼
退出,再用郵箱+密碼登陸.
退出,再用手機號+密碼登陸.
哈哈。看到沒,三種登陸方式都已經成功了.
對與數據檢驗,我這裏沒有去作,不過,能夠在我下一篇實戰用戶註冊這塊來彌補.
若是想了解更多,請關注咱們的公衆號
公衆號ID:opdevos
掃碼關注