Python Django 學習紀錄(七) 使用者管理
- 在 django.contrib 套件的 auth 應用程式中,以內建 User(使用者) 資料表,可以記錄使用者的個人資訊
- 在 is _authenticated可以檢查使用者是否認證過。
- auth.login() 接收 request 、user 兩個參數,登入成功後會產生一個 Session
- auth.logout() 可以進行登出動作,登出成功會將原來的 Session 刪除
一、Django auth 簡介:
在 django.contrib 套件的 auth 應用程式中,已內建 User(使用者) 資料表,使用這個資料表可以記錄使用者的個人資訊,包括帳號、密碼......等。
1.安裝 Django auth App
要使用 auth 必須安裝 auth 的 App ,Django 專案建立完成後預設已自動加入 auth 的 App 。
2.開啟 login 專案
- 建立一個名為 login 的專案
- 建立名為 loginApp 的 App
- 建立 templates 目錄、static 目錄
- 建立makemigrations 資料檔,並利用 migrate 將模型與資料庫同步
- 最後完成<setting.py的設定>
以下為<setting.py>設定:
""" Django settings for login project. Generated by 'django-admin startproject' using Django 2.0.1. For more information on this file, see https://docs.djangoproject.com/en/2.0/topics/settings/ For the full list of settings and their values, see https://docs.djangoproject.com/en/2.0/ref/settings/ """ import os # Build paths inside the project like this: os.path.join(BASE_DIR, ...) BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) # Quick-start development settings - unsuitable for production # See https://docs.djangoproject.com/en/2.0/howto/deployment/checklist/ # SECURITY WARNING: keep the secret key used in production secret! SECRET_KEY = '6os_6u4$-^oivhtuoa$b=jbse&^ezbcz+r4mv5ga%)+j*54m07' # SECURITY WARNING: don't run with debug turned on in production! DEBUG = True ALLOWED_HOSTS = [] # Application definition INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', #此為 auth 的 App 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'loginapp', #新增的App ] MIDDLEWARE = [ 'django.middleware.security.SecurityMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware', 'django.middleware.common.CommonMiddleware', 'django.middleware.csrf.CsrfViewMiddleware', 'django.contrib.auth.middleware.AuthenticationMiddleware', #確認已加入 'django.contrib.messages.middleware.MessageMiddleware', 'django.middleware.clickjacking.XFrameOptionsMiddleware', ] ROOT_URLCONF = 'login.urls' TEMPLATES = [ { 'BACKEND': 'django.template.backends.django.DjangoTemplates', 'DIRS': [os.path.join(BASE_DIR,'templates')], #加上 templates 路徑 'APP_DIRS': True, 'OPTIONS': { 'context_processors': [ 'django.template.context_processors.debug', 'django.template.context_processors.request', 'django.contrib.auth.context_processors.auth', 'django.contrib.messages.context_processors.messages', ], }, }, ] WSGI_APPLICATION = 'login.wsgi.application' # Database # https://docs.djangoproject.com/en/2.0/ref/settings/#databases DATABASES = { 'default': { 'ENGINE': 'django.db.backends.sqlite3', 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'), } } # Password validation # https://docs.djangoproject.com/en/2.0/ref/settings/#auth-password-validators AUTH_PASSWORD_VALIDATORS = [ { 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator', }, { 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator', }, { 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator', }, { 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator', }, ] # Internationalization # https://docs.djangoproject.com/en/2.0/topics/i18n/ LANGUAGE_CODE = 'zh-Hant' #設定語系 TIME_ZONE = 'Asia/Taipei' #設定時區 USE_I18N = True USE_L10N = True USE_TZ = True # Static files (CSS, JavaScript, Images) # https://docs.djangoproject.com/en/2.0/howto/static-files/ STATIC_URL = '/static/' STATICFILES_DIRS=[ #設定 static 路徑 os.path.join(BASE_DIR,'static'), ]
接著在 <urls.py> 定義下列的 URL:
先將還不會用到的路徑註解掉,之後要使用時再陸續打開,以免之後運行伺服器會產生找不到路徑中函數的問題:
from django.contrib import admin from django.urls import path from loginapp import views urlpatterns = [ path('admin/', admin.site.urls), # path('', views.index), # path('index/', views.index), # path('login/', views.login), # path('logout/', views.logout), #path('adduser/', views.adduser), ]
(1) 登入 admin 後台管理
接下來先關閉server,要建立管理者帳號密碼來登入admin
這邊帳號先以admin,信箱設為admin@admin.com,密碼設為aa000000(不能設為全數字)
創建完後就可以再次啟動伺服器,輸入「127.0.0.1:8000/admin」就會開啟admin登入畫面
(2) 在 User 資料表新增使用者
點選 使用者 項目的 新增 鈕,以管理介面在 User 資料表新增一筆資料。
按 儲存 進入詳細頁面,權限預設 有效 代表此帳號已經生效
往下捲動可以設定 工作人員狀態、超級使用者狀態 和 群組,工作人員狀態可以管理後台資料庫,這邊都先不做選取,捲動頁面到最下方按下 儲存。
由於前面 工作人員狀態 未勾選,所以這邊顯示狀態為「 X 」,第一筆資料則是一開始創建的管理者帳號。
3.讀取 Django auth 使用者
使用 auth 就可以達到使用者驗證的動作。
User資料表 就是使用者用戶的資料,可以使用models 模組的 objects.get() 和 objects.all() 方法來取的資料。
例如、以 objects.all() 方法讀取 User資料表 的所有資料
from django.contrib.auth.models import User #記得要先導入套件 User.objects.all()
因為查詢資料時常會發生例外情況,所以通常會以 try/expect 捕捉錯誤:
from django.contrib.auth.models import User #記得要先導入套件 try: user = User.objects.get(username='ivanpotato') expect: user = None
4.使用 HttpRequest.user 物件
以 HttpRequest.user 可以取得一個 User 物件或是一個 AnonymousUser 物件,來判斷是否已經登錄(前者為登錄,後者為未登錄)。
以 is_authenticated 可以檢查使用者是否認證過,User會傳回 True,AnonymousUser 會傳回 False。
例如、建立 index() 自訂函式顯示<index.html>首頁,並判斷使用者是否認證過,若通過則以 username 取得其名稱:
def index(request): if request.user.is_authenticated: name = request.user.username return render(request,"index.html",locals())
以下為 User 物件常用的屬性:
屬性 |
說明 |
username | 使用者帳號 |
first_name | 名字 |
last_name | 姓氏 |
信箱 | |
password | 密碼(加密) |
is_staff | 布林值,設定是否可登入 admin 後台 |
is_active | 布林值,設定使用者是否有效(可登入) |
is_superuser | 布林值,設定使用者是否擁有全部權限 |
last_login | 上一次登錄的日期時間 |
date_joined | 使用者創建的日期時間 |
以下為 User 物件常用的方法:
方法 |
說明 |
get_username() | 取得使用者帳號 |
is_anonymous() | 是否為匿名用戶 |
is_authenticated() | 確認使用者是否認證過 |
get_full_name() | 取得名字和姓氏,中間有一空格 |
get_short_name() | 取得姓氏 |
範例1.新增使用者
欲達成目標:
- 利用程式直接在 auth 的 User資料表 中新增一個使用者(包含帳號、密碼、信箱)
請打開 loginapp 裡的<view.py>,先導入所有之後會用到的套件,接著寫一個名為 adduser() 的自訂函數:
from django.shortcuts import render,redirect # 加入 redirect 套件 from django.contrib.auth import authenticate from django.contrib import auth from django.http import HttpResponse from django.contrib.auth.models import User def adduser(request): try: user = User.objects.get(username="test") #以 user 取得名稱為「test」的資料 except: user = None #若「test」不存在則設定為 None if user != None: message = user.username + " 帳號已經建立! " return HttpResponse(message) else: #建立 test 帳號 user = User.objects.create_user("test","test@test.com.tw","aa000000") user.first_name = "victor" user.last_name = "chen" user.is_staff = "True" user.save() #將資料寫入資料庫 return redirect('/admin/') #若成功建立,重新導向至 admin 管理介面,方便觀察建立完成的資料
最後記得在<urls.py>新增 adduser 的url路徑(或是去掉之前的註解)
在瀏覽器網址列輸入「127.0.0.1:8000/adduser」網頁執行結果如下:
建立成功會直接導向 "/admin/"
可以點選使用者查看剛才新增的資料
若是已經建立則會看到以下訊息
二、登入和登出:
善用 User資料表 可以對使用者進行登入驗證,一般是檢查帳號、密碼
1.登入驗證
利用 auth 內建的 auth.authenticate 方法可以完成使用者登入驗證
auth = auth.authenticate(username= 帳號, password= 密碼)
auth.authenticate 接收 username、password 兩個參數,如果帳號、密碼正確,會傳回一個具名的 User 物件,否則傳回 None。
user.is_active 屬性檢查該使用者是否有效,若失效 auth.authenticate 就算驗證通過也會傳回 None
2.登入
如果 user.is_active 為 True 就是有效使用者而且通過驗證,這時就可以 auth.login() 進行登入:
auth.login(request,user)
auth.login() 接收 request、user 兩個參數,登入後會產生一個 Session,直到登出時才會被刪除。
例如、通過驗證使用者以 user物件登入:
if user.is_active: auth.login(request,user)
3.登出
auth.logout() 可以進行登出動作,登出之後,就會將原來的 Session 清除:
auth.logout(request)
範例2.使用者登入和登出
欲達成目標:
- 建立<index.html>首頁,入使用者尚未通過,顯示「你尚未登入哦~」訊息,按 登入 進行登入動作
- 進入 login 登入畫面,輸入帳號密碼後,按 登入 鈕
- 登入成功後,顯示「歡迎光臨」,按 登出 進行登出動作
請打開 loginapp 裡的<view.py>,先導入所有之後會用到的套件,接著寫一個名為 login() 和一個名為 logout() 的自訂函數:
def login(request): if request.method == 'POST': #如果是 <login.html> 按登入鈕傳送 name = request.POST['username'] #取得表單傳送的帳號、密碼 password = request.POST['password'] user = auth.authenticate(username=name, password=password) #使用者驗證 if user is not None: #若驗證成功,以 auth.login(request,user) 登入 if user.is_active: auth.login(request,user) return redirect('/index/') #登入成功產生一個 Session,重導到<index.html> message = '登入成功!' else: message = '帳號尚未啟用!' else: message = '登入失敗!' return render(request,"login.html",locals()) #登入失敗則重導回<login.html> def logout(request): auth.logout(request) #登出成功清除 Session,重導到<index.html> return redirect('/index/')
接著在 templates目錄中創建<index.html>模版
<!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html"; charset="utf-8"> <title>首頁</title> </head> <body> <h2>登入登出測試首頁</h2> {% if request.user.is_authenticated %} <!-- 檢查使用者是否通過驗證 --> 歡迎光臨:{{name}} <p><a href="/logout/">登出</a></p> {% else %} <p>你尚未登入哦~</p> <a href="/login/">登入</a> {% endif %} <span style="color: red">{{message}}</span> </body> </html>
再來在 templates目錄中創建<login.html>模版
<!DOCTYPE html> <html> <head> <title>登入頁面</title> </head> <body> <form action="." method="POST" name="form1"> {% csrf_token %} <div>帳號:<input type="text" name="username" id="username" /></div> <div>密碼:<input type="password" name="password" id="password" /></div> <div> <input type="submit" name="button" id="button" value="登入" /> </div> </form> <span style="color: red">{{message}}</span> </body> </html>
最後記得在<urls.py>新增所有會用到的的url路徑(或是去掉之前的註解)
在瀏覽器網址列輸入「127.0.0.1:8000」或是「127.0.0.1:8000/index/」網頁執行結果如下:
按 登入 進行登入動作
輸入帳號密碼點選 登入 鈕,若登入失敗則顯示以下訊息
按輸入帳號密碼點選 登入 鈕,若登入成功,則導向<index.html>頁面,按 登出 則進行登出動作