被解放的姜戈06 假作真時


作者:Vamei 出處:http://www.cnblogs.com/vamei 歡迎轉載,也請保留這段聲明。謝謝!

 

之前了解了:

  • 創建Django項目
  • 數據庫
  • 模板
  • 表格提交
  • admin管理頁面

上面的功能模塊允許我們做出一個具有互動性的站點,但無法驗證用戶的身份。我們這次了解用戶驗證部分。通過用戶驗證,我們可以根據用戶的身份,提供不同的服務。

 

一個Web應用的用戶驗證是它的基本組成部分。我們在使用一個應用時,總是從“登錄”開始,到“登出”結束。另一方面,用戶驗證又和網站安全、數據庫安全息息相關。HTTP協議是無狀態的,但我們可以利用儲存在客戶端的cookie或者儲存在服務器的session來記錄用戶的訪問。 

Django有管理用戶的模塊,即django.contrib.auth。你可以在mysite/settings.py里看到,這個功能模塊已經注冊在INSTALLED_APPS中。利用該模塊,你可以直接在邏輯層面管理用戶,不需要為用戶建立模型,也不需要手工去實現會話。

 

 

 

“為了救你的愛人出來,我們要演一場戲。”

 

創建用戶

你可以在admin頁面直接看到用戶管理的對話框,即Users。從這里,你可以在這里創建、刪除和修改用戶。點擊Add增加用戶daddy,密碼為daddyiscool。

在admin頁面下,我們還可以控制不同用戶組對數據庫的訪問權限。我們可以在Groups中增加用戶組,設置用戶組對數據庫的訪問權限,並將用戶加入到某個用戶組中。

在這一章節中,我們創立一個新的app,即users。下文的模板和views.py,都針對該app。

 

"你這套新衣服,還真像那么回事",德國人說。

 

用戶登錄

我們建立一個簡單的表格。用戶通過該表格來提交登陸信息,並在Django服務器上驗證。如果用戶名和密碼正確,那么登入用戶。

我們首先增加一個登錄表格:

<form role="form" action="/login" method="post">
      <label>Username</label>
      <input type="text" name='username'>
      <label>Password</label>
      <input name="password" type="password">
      <input type="submit" value="Submit">
 </form>

 

我們在views.py中,定義處理函數user_login(),來登入用戶:

# -*- coding: utf-8 -*-
from django.shortcuts import render, redirect from django.core.context_processors import csrf from django.contrib.auth import *

def user_login(request): ''' login '''
    if request.POST: username = password = '' username = request.POST.get('username') password = request.POST.get('password') user = authenticate(username=username, password=password) if user is not None and user.is_active: login(request, user) return redirect('/') ctx = {} ctx.update(csrf(request)) return render(request, 'login.html',ctx)

上面的authenticate()函數,可以根據用戶名和密碼,驗證用戶信息。而login()函數則將用戶登入。它們來自於django.contrib.auth。

 

作為替換,我們可以使用特別的form對象,而不自行定義表格。這將讓代碼更簡單,而且提供一定的完整性檢驗。

練習. 使用contrib.auth.forms.AuthenticationForm。來簡化上面的模板和處理函數。

 

德國人還是不忘一再叮囑,"記住,我們可不是什么賞金獵人。" 

 

登出

有時用戶希望能銷毀會話。我們可以提供一個登出的URL,即/users/logout。登入用戶訪問該URL,即可登出。在views.py中,增加該URL的處理函數:

# -*- coding: utf-8 -*-
from django.shortcuts import redirect def user_logout(request): ''' logout URL: /users/logout ''' logout(request) return redirect('/')

我們修改urls.py,讓url對應user_logout()。訪問http://127.0.0.1/users/logout,就可以登出用戶。

 

德國人壓低聲音,“哦,我是來救你的,我們要演一出戲。” 

 

views.py中的用戶

上面說明了如何登入和登出用戶,但還沒有真正開始享受用戶驗證帶來的好處。用戶登陸的最終目的,就是為了讓服務器可以區別對待不同的用戶。比如說,有些內容只能讓登陸用戶看到,有些內容則只能讓特定登陸用戶看到。我們下面將探索如何實現這些效果。

 

在Django中,對用戶身份的檢驗,主要是在views.py中進行。views.py是連接模型和視圖的中間層。HTTP請求會轉給views.py中的對應處理函數處理,並發回回復。在views.py的某個處理函數准備HTTP回復的過程中,我們可以檢驗用戶是否登陸。根據用戶是否登陸,我們可以給出不同的回復。最原始的方式,是使用if式的選擇結構: 

# -*- coding: utf-8 -*-
from django.http import HttpResponse def diff_response(request): if request.user.is_authenticated(): content = "<p>my dear user</p>"
    else: content = "<p>you wired stranger</p>"
    return HttpResponse(content)

 

可以看到,用戶的登錄信息包含在request.user中,is_authenticated()方法用於判斷用戶是否登錄,如果用戶沒有登錄,那么該方法將返回false。該user對象屬於contrib.auth.user類型,還有其它屬性可供使用,比如

屬性 功能
get_username() 返回用戶名
set_password() 設置密碼
get_fullname() 返回姓名
last_login 上次登錄時間
date_joined   賬戶創建時間

練習. 實驗上面的處理函數的效果。

 

在Django中,我們還可以利用裝飾器,根據用戶的登錄狀況,來決定views.py中處理函數的顯示效果。相對於上面的if結構,裝飾器使用起來更加方便。下面的user_only()是views.py中的一個處理函數。

from django.contrib.auth.decorators import login_required from django.http import HttpResponse @login_required def user_only(request): return HttpResponse("<p>This message is for logged in user only.</p>")

注意上面的裝飾器login_required,它是Django預設的裝飾器。user_only()的回復結果只能被登錄用戶看到,而未登錄用戶將被引導到其他頁面。

 

Django中還有其它的裝飾器,用於修飾處理函數。相應的http回復,只能被特殊的用戶看到。比如user_passes_test,允許的用戶必須滿足特定標准,而這一標准是可以用戶自定義的。比如下面,在views.py中增添: 

from django.contrib.auth.decorators import user_passes_test
from django.http import HttpResponse
def name_check(user): return user.get_username() == 'vamei' @user_passes_test(name_check) def specific_user(request): return HttpResponse("<p>for Vamei only</p>")

 

裝飾器帶有一個參數,該參數是一個函數對象name_check。當name_check返回真值,即用戶名為vamei時,specific_user的結果才能被用戶看到。

 

德國人羞澀的笑笑,“我確實對她有那么點好感。” 

 

模板中的用戶

進一步,用戶是否登陸這一信息,也可以直接用於模板。比較原始的方式是把用戶信息直接作為環境數據,提交給模板。然而,這並不是必須的。事實上,Django為此提供了捷徑:我們可以直接在模板中調用用戶信息。比如下面的模板:

{% if user.is_authenticated %} <p>Welcome, my genuine user, my true love.</p> {% else %} <p>Sorry, not login, you are not yet my sweetheart. </p> {% endif %}

不需要環境變量中定義,我們就可以直接在模板中引用user。這里,模板中調用了user的一個方法,is_authenticated,將根據用戶的登錄情況,返回真假值。需要注意,和正常的Python程序不同,在Django模板中調用方法並不需要后面的括號。

 

練習. 增加處理函數,顯示該模板,然后查看不同登錄情況下的顯示結果。

 

管家冷不丁的說,“你認識他們?!” 

 

用戶注冊

我們上面利用了admin管理頁面來增加和刪除用戶。這是一種簡便的方法,但並不能用於一般的用戶注冊的情境。我們需要提供讓用戶自主注冊的功能。這可以讓站外用戶提交自己的信息,生成自己的賬戶,並開始作為登陸用戶使用網站。

用戶注冊的基本原理非常簡單,即建立一個提交用戶信息的表格。表格中至少包括用戶名和密碼。相應的處理函數提取到這些信息后,建立User對象,並存入到數據庫中。

我們可以利用Django中的UserCreationForm,比較簡潔的生成表格,並在views.py中處理表格:

from django.contrib.auth.forms import UserCreationForm from django.shortcuts import render, redirect from django.core.context_processors import csrf def register(request): if request.method == 'POST': form = UserCreationForm(request.POST) if form.is_valid(): new_user = form.save() return redirect("/") else: form = UserCreationForm() ctx = {'form': form} ctx.update(csrf(request)) return render(request, "register.html", ctx)

 

相應的模板register.html如下:

<form action="" method="post"> {% csrf_token %} {{ form.as_p }} <input type="submit" value="Register">
</form>

 

“騙子,你們這些騙子”,庄園主怒吼着。

 

總結

正如我們上面提到的,用戶登陸系統的最大功能是區分登入和未登入用戶,向他們提供不同的內容和服務。

我們看到了用戶驗證的基本流程,也看到了如何在views.py和模板中區分用戶。

 

兩桿槍,一支指着德國人,一支指着姜戈。

 

歡迎閱讀“被解放的姜戈”系列文章。

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM