close

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 專案

  1. 建立一個名為 login 的專案
  2. 建立名為 loginApp 的 App 
  3. 建立 templates 目錄、static 目錄
  4. 建立makemigrations 資料檔,並利用 migrate 將模型與資料庫同步
  5. 最後完成<setting.py的設定>

71.JPG

 

 以下為<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(不能設為全數字)

25.JPG

創建完後就可以再次啟動伺服器,輸入「127.0.0.1:8000/admin」就會開啟admin登入畫面

26.JPG

 

 

(2) 在 User 資料表新增使用者

點選 使用者 項目的 新增 鈕,以管理介面在 User 資料表新增一筆資料。

73.JPG

儲存 進入詳細頁面,權限預設 有效 代表此帳號已經生效

74.JPG

往下捲動可以設定 工作人員狀態、超級使用者狀態群組工作人員狀態可以管理後台資料庫,這邊都先不做選取,捲動頁面到最下方按下 儲存

75.JPG

由於前面 工作人員狀態 未勾選,所以這邊顯示狀態為「 X 」,第一筆資料則是一開始創建的管理者帳號。

76.JPG

 

 

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 物件常用的屬性:

User物件常用的屬性

屬性

說明
username 使用者帳號
first_name 名字
last_name 姓氏
email 信箱
password 密碼(加密)
is_staff 布林值,設定是否可登入 admin 後台
is_active 布林值,設定使用者是否有效(可登入)
is_superuser 布林值,設定使用者是否擁有全部權限
last_login 上一次登錄的日期時間
date_joined 使用者創建的日期時間

 

以下為 User 物件常用的方法:

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/"

77.JPG

可以點選使用者查看剛才新增的資料

78.JPG

若是已經建立則會看到以下訊息

79.JPG

 

二、登入和登出:

善用 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/」網頁執行結果如下:

80.JPG

登入 進行登入動作

81.JPG

輸入帳號密碼點選 登入 鈕,若登入失敗則顯示以下訊息

82.JPG

按輸入帳號密碼點選 登入 鈕,若登入成功,則導向<index.html>頁面,按 登出 則進行登出動作

83.JPG

arrow
arrow
    全站熱搜
    創作者介紹
    創作者 ivankao 的頭像
    ivankao

    IvanKao的部落格

    ivankao 發表在 痞客邦 留言(0) 人氣()