
上篇文章中講到 Django 如何啟動以及配置 sessions 功能。sessions 功能用是跟蹤用戶的狀態(tài),經(jīng)常結(jié)合 Cookie 功能實(shí)現(xiàn)自動登錄功能。 所謂的“自動登錄”指的是:我們登錄一些網(wǎng)站,在不關(guān)閉瀏覽器以及距離上次登錄時(shí)間不是很長的情況下。無論我們在新的標(biāo)簽頁打開網(wǎng)站,還是關(guān)閉頁面重新打開網(wǎng)站,登錄狀態(tài)一直保持著。本文內(nèi)容有兩個(gè):一是利用 Django 實(shí)現(xiàn)自動登錄功能,二是揭開“自動登錄”的神秘面紗。
1 新建項(xiàng)目
我為了將本系列所有文章的示例代碼保持集中狀態(tài),所以直接在 Django_demo 項(xiàng)目中創(chuàng)建應(yīng)用。如果第一次看這文章,需要先創(chuàng)建項(xiàng)目(project),再創(chuàng)建應(yīng)用(app)。我新建的應(yīng)用是 demo_session。

然后在 setting.py 中啟動請用,并檢查 sessions 組件是否啟動。

因?yàn)樾枰?Cookie 功能,所以同樣需要在 settings.py 增加一些配置。
SESSION_COOKIE_NAME = "sessionid" # Session的cookie保存在瀏覽器上時(shí)的key
SESSION_COOKIE_PATH = "/" # Session的cookie保存的路徑(默認(rèn))
SESSION_COOKIE_DOMAIN = None # Session的cookie保存的域名(默認(rèn))
SESSION_COOKIE_SECURE = False # 是否Https傳輸cookie
SESSION_COOKIE_HTTPONLY = True # 是否Session的cookie只支持http傳輸(默認(rèn))
SESSION_COOKIE_AGE = 1209600 # Session的cookie失效日期(2周)(默認(rèn))
SESSION_SAVE_EVERY_REQUEST = False # 是否設(shè)置關(guān)閉瀏覽器使得Session過期
SESSION_COOKIE_AT_BROWSER_CLOSE = False # 是否每次請求都保存Session,默認(rèn)修改之后才能保存
如果你將 SESSION_SAVE_EVERY_REQUEST 設(shè)置為 True, 那么關(guān)閉瀏覽器之后,需要重新登錄。
2 流程
應(yīng)用中會涉及到 3 個(gè)頁面,所以我繪制流程圖幫助理解。

3 實(shí)現(xiàn)
3.1 新建 model
服務(wù)器接收到瀏覽器傳送過來登錄信息,需要驗(yàn)證賬號和密碼等信息。所以需要新建 model 保存信息,以便后續(xù)跟數(shù)據(jù)庫做校驗(yàn)。這里我只是簡單保存信息,登錄驗(yàn)證后續(xù)講解。
class User(models.Model):
username = models.CharField(max_length=20) # 賬號
password = models.CharField(max_length=20) # 密碼
nickname = models.CharField(max_length=20) # 昵稱
3.2 新建 form
用戶將登錄信息發(fā)送給服務(wù)器是用到 POST 請求,所以需要創(chuàng)建表單。在應(yīng)用目錄下新建名為 forms 目錄,然后創(chuàng)建 forms.py 文件。
from django.forms import ModelForm, TextInput, PasswordInput
from demo_session.models import User
class UserForm(ModelForm):
class Meta:
model = User
fields = ['username', 'password', ] # 只顯示 model 中指定的字段
# 指定呈現(xiàn)樣式字段、指定 CSS 樣式
widgets = {
'username': TextInput(attrs={'class': 'text',
'value': 'monkey'}),
'password': PasswordInput(attrs={'value': '13245678', })
}
3.3 新建視圖
頁面一共有三個(gè),分別是登錄、首頁、登出。具體實(shí)現(xiàn)如下:
# view.py
from django.http import HttpResponseRedirect, HttpResponse
from django.shortcuts import render
from demo_session.form.forms import UserForm
# 用戶登錄
def login_view(request):
# 過濾 POST 方法的請求
if request.method == 'POST':
userfrom = UserForm(request.POST)
# 驗(yàn)證表單
if userfrom.is_valid():
username = userfrom.cleaned_data['username']
password = userfrom.cleaned_data['password']
# ... 執(zhí)行驗(yàn)證登錄信息操作
# 將等你信息傳遞給 Session 對象, 實(shí)際應(yīng)用中不建議這么操作
request.session['username'] = username
# 跳轉(zhuǎn)到頁面
return HttpResponseRedirect('/index/')
else:
# 不是 GET 請求則顯示表單
userfrom = UserForm()
template_view = 'login.html'
return render(request, template_view, {'userfrom': userfrom})
# 成功登錄之后, 跳轉(zhuǎn)首頁
def index_view(request):
username = request.session.get('username', '')
# print(username)
template_view = 'index.html'
return render(request, template_view, {'username': username})
# 登出操作
def logout_view(request):
# 刪除 session
del request.session['username']
return HttpResponse('登出成功')
3.4 對應(yīng)模板
視圖 login_view, index_view 對應(yīng)的模板是 login.html, index.html。
其中 login.html 的實(shí)現(xiàn)如下:
{% load staticfiles %}
<!DOCTYPE html>
<html lang="{{ LANGUAGE_CODE|default:"en-us" }}">
<head>
<meta charset="UTF-8">
<title>登錄</title>
<link href="{% static 'css/style.css' %}" rel="stylesheet" type='text/css' >
<!--webfonts-->
<link href="{% static 'css/font.css' %}" rel='stylesheet' type='text/css'>
<meta name="viewport" content="width=device-width, initial-scale=1">
<script type="application/x-javascript">
addEventListener("load", function() { setTimeout(hideURLbar, 0); }, false);
function hideURLbar(){ window.scrollTo(0,1); }</script>
</head>
<body>
<div class="main">
<div class="login-form">
<h1>Member Login</h1>
<div class="head">
<img src="{% static 'images/user.png' %}" alt=""/>
</div>
<form action="" method="POST">
{% csrf_token %}
{{ userfrom.username }}
{{ userfrom.password }}
<div class="submit"><input type="submit" value="login" ></div>
<p><a href="#">Forgot Password ?</a></p>
</form>
</div>
</div>
</body>
</html>
index.html 的實(shí)現(xiàn)如下:
<!DOCTYPE html>
<html lang="{{ LANGUAGE_CODE|default:"en-us" }}">
<head>
<meta charset="UTF-8">
<title>首頁</title>
</head>
<body>
<div >
<h3>歡迎 {{username}} 到來~</h3>
<div class="submit"><a href="/logout"><input type="submit" value="退出登錄" ></a></div>
</div>
</body>
</html>
3.5 配置路由
最后一步,在 urls.py 中配置訪問路徑:
from demo_session.views import login_view, index_view, logout_view
urlpatterns = [
# demo_session
path('login/', login_view, name='login'),
path('index/', index_view, name='index'),
path('logout/', logout_view, name='index'),
]
4 實(shí)現(xiàn)效果
用戶訪問 http://127.0.0.1/login 進(jìn)行登錄操作。

當(dāng)點(diǎn)擊 login 成功之后,會跳轉(zhuǎn)到首頁,首頁會顯示用戶名。同時(shí),Cookie 中多了一個(gè) sessionid 的字段。這字段名就是我們在 setttings.py 定義的。

查詢數(shù)據(jù)庫 django_session 表的內(nèi)容,會多出一條數(shù)據(jù)。

表中的字段含義如下:
- session_key: 就是服務(wù)器給用戶返回的id。在瀏覽器當(dāng)中,這個(gè)值是保存為sessionid
- session_data: 這是一個(gè)加密后的信息,用來保存用戶名和密碼等信息
- expire_data: 過期時(shí)間,Django可以設(shè)置過期時(shí)間
在新的標(biāo)簽頁中打開首頁,依然能看到 username 信息。這證明能自動登錄。

如果用戶退出登錄,再訪問首頁。這時(shí)會發(fā)現(xiàn)看不到了 username 信息了。

5 小結(jié)
實(shí)現(xiàn)自動登錄功能其實(shí)不難,只需要在 Django 的 Sessions 組件。然后根據(jù)場景需要,在 settings.py 配置 session 以及 cookie 等信息。
往前 Django 學(xué)習(xí)筆記文章
Django 學(xué)習(xí)筆記之環(huán)境搭建
Django 學(xué)習(xí)筆記之初始
Django 學(xué)習(xí)筆記之視圖與URL配置
Django 學(xué)習(xí)筆記之模板
Django 學(xué)習(xí)筆記之模型(上)
Django 學(xué)習(xí)筆記之模型(下)
Django 學(xué)習(xí)筆記之后臺管理
Django 學(xué)習(xí)筆記之模型表單
Django 學(xué)習(xí)筆記之使用舊數(shù)據(jù)庫
Django 實(shí)戰(zhàn)1:搭建屬于自己社工查詢系統(tǒng)(上)
Django 實(shí)戰(zhàn)1:搭建屬于自己社工查詢系統(tǒng)(下)
Django 學(xué)習(xí)筆記之模型高級用法(上)
Django 學(xué)習(xí)筆記之模型高級用法(下)
Django 實(shí)現(xiàn)分頁功能
Django 使用會話( sessions )功能
本文原創(chuàng)發(fā)布于微信公眾號「極客猴」,歡迎關(guān)注第一時(shí)間獲取更多原創(chuàng)分享