什麼叫狀態保持?html
就好比說咱們登錄一個網站,登錄以後的當前頁面顯示的是登錄狀態,可是咱們要再跳轉同一網站的其餘頁面,則顯示的未登陸狀態,狀態保持就是:咱們在當前頁面登錄後,再訪問其餘頁面時也顯示爲登錄狀態,這就是狀態保持python
爲何會出現狀態不保持?redis
由於咱們http協議是無狀態的,它每一次請求都是一個新的請求。在服務器和客戶端創建鏈接後,服務器與客戶端的每一次會話都是一次http協議(客戶端發送請求與服務器對請求的響應)的體現。數據庫
爲何要進行狀態保持?django
在一段時間內跟蹤請求者的狀態,實現跨頁面訪問當前的請求者數據。而且不一樣的請求者之間不會共享這個數據,與登錄的請求者是一一對應的。瀏覽器
如何實現狀態保持?緩存
咱們能夠在客戶端或者服務端把有關會話的數據存儲起來。安全
狀態保持的存儲方式:服務器
【cookie的擴展知識】cookie
cookie是不安全的,且長度有限(4kb)容易被截獲,最多隻能存儲20條數據,因此咱們不能用它來存儲敏感數據(如:帳號,密碼等),咱們通常用它來存儲一個token值,每次發送給服務器cookie值時就是發送的這個token值。
瀏覽器用戶登陸過程和cookie:
瀏覽器用戶登陸時會發送給服務器對應信息(帳號和密碼),首先服務器會去redis中去驗證用戶名/密碼,如有用戶的相關信息則redis將確認信息返給服務器,若沒有則去數據庫中驗證token,若數據庫中有,則先把對應數據(用戶名/密碼)存到redis中,再把確認信息返回給服務器,服務器做出判斷後再返回信息(攜帶一個token字符串給cookie)給瀏覽器表示登錄成功/失敗(這個token也會被存到數據庫中一份(當前用戶下),下一次用戶訪問數據的時候,瀏覽器則直接帶着token去服務器,服務器則直接進行token驗證(登錄成功以後的數據訪問直接找redis))
【和cookie/session類似的狀態保持存儲方式】
sessionStorage(h5):關閉客戶端就不存在了
【其餘擴展知識】
cookie的適用場景:數據量小;數據須要隨http請求傳遞到服務端;存儲有具體時限的數據;
localStorage適用場景:數據大於4k;須要跨標籤頁使用數據;長期存儲數據;
sessionStorage適用場景:數據只在本次會話有效;數據僅在當前標籤頁有效;
綜上所述:
由於cookie的不安全,因此咱們選擇狀態保持的存儲方式:session,它是將用戶數據存儲在數據庫中的存儲方式。
python-django-啓用session:
配置settings.py文件
INSTALLED_APPS = ['django.contrib.sessions',] # 默認是啓用的
MIDDLEWARE = [ 'django.contrib.sessions.middleware.SessionMiddleware',] # 默認啓用的
啓用session後,每一個HttpResponse對象都有一個session屬性(一個相似於字典的對象)
python-django-使用session:
session中的方法:
get(key,default=None) | 根據鍵獲取session值 |
clear() | 清空當前全部會話 |
flush() | 刪除當前會話並刪除會話的cookie |
set_expiry() | 設置session過時時間(默認爲兩個星期後過時): 時間對象必須爲整數:表示多少秒後過時 設置具體時間對象(2019-11-25):表示2019-11-25這個時間過時 設置爲0:表示關閉瀏覽器時過時 設置爲None:永不過時 |
setdefault(‘k1’,123) | 若session存在則不設置 |
keys() | session鍵 |
values() | session值 |
items() | session鍵值對 |
delete(‘session_key') | 刪除當前用戶的全部session數據 |
clear_expired() | 將全部session失效日期小於當前日期的數據刪除 |
exists(’session_key') | 檢查用戶session的隨機字符串是否在數據庫中 |
舉個栗子:
from django.contrib.auth import logout from django.shortcuts import render,redirect def main(request): # 取出session值 username = request.session.get('name', '遊客') # session中找不到username值則默認爲’遊客’ return render(request,'myapp/main.html',{'username':username}) def login(request): return render(request,'myapp/login.html') def showmain(request): print("****") username = request.POST.get('username') # 存儲session的值 request.session['name'] = username # request.session.set_expiry(10) # 表示10秒後過時 return redirect('/sunck/main/') def quit(request): # 清除session logout(request) # 推薦使用 # request.session.clear() # request.session.flush() # request.session.delete() return redirect('/sunck/main/')
對應url:
對應html文件:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>個人</title> </head> <body> <h1>歡迎:{{username}}</h1> <a href="/sunck/login">登錄</a> <a href="/sunck/quit">退出登錄</a> </body> </html>
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>登錄</title> </head> <body> <form action="/sunck/showmain/" method="post"> <input type="text" name="username"/> <input type="submit" value="登錄"/> </form> </body> </html>
python-django-session的存儲位置:
(都是在settings.py文件中配置)
四種存儲配置:
數據庫( 推薦) | 默認存儲在數據庫中 SESSION_ENGINE = 'django.contrib.session.backends.db' |
緩存( redis中)(推薦) | 只存儲在主機本地內存中,若丟失不能找回,但比數據庫快 SESSION_ENGINE = 'django.contrib.session.backends.cached' |
數據庫和緩存 | 優先從本地緩存中讀取,讀不到則去數據庫中獲取 SESSION_ENGINE = 'django.contrib.session.backends.cached_db' |
文件 | 須要進行兩項配置: SESSION_ENGINE = 'django.contrib.session.backends.file' SESSION_FILE_PATH=None # 默認爲none,則使用tempfile模塊獲取臨時地址tempfile.gettempdir()並存儲,也可設置地址 |