一.狀態保持的概述
http協議是無狀態的。下一次去訪問一個頁面時並不知道上一次對這個頁面做了什么。因此引入了cookie、session兩種方式來配合解決此問題。
Duplicate entry:重復條目
二、Cookie(存儲在客戶端)
- cookie是由服務器生成,存儲在瀏覽器端的一小段文本信息。
1.1 cookie的特點:
- 服務器通過HttpRessponse的對象set_cookie設置cookie:
HttpRessponse.set_cookie
- 瀏覽器以鍵值對方式進行存儲。
- 通過瀏覽器訪問一個網站時,會將瀏覽器存儲的跟網站相關的所有cookie信息發送給該網站的服務器。(服務器取cookies:
request.COOKIES
) - cookie是基於域名安全的。www.baidu.com www.tudou.com
- cookie是有過期時間的,如果不指定,默認關閉瀏覽器之后cookie就會過期。
1.2 cookie基礎使用案例
1)app1/views.py編寫設置cookie設置/獲取函數
1.設置cookie:/setCookie
2.獲取cookie:/getCookie
#1.設置cookie:/setCookie
def set_cookie(request):
'''請求設置cookie'''
response=HttpResponse('設置cookie') #【1】
response.set_cookie('name','jim')#【2】
return response
#2.獲取cookie:/getCookie
def get_cookie(request):
'''服務器獲取瀏覽器的cookie'''
name=request.COOKIES['name']#【3】注意必須大寫
return HttpResponse(name)
2)配置app1/urls.py
設置cookie頁
獲取cookie頁
from django.urls import path,re_path
from . import views
re_path('^setCookie$',views.set_cookie),#設置cookie頁
re_path('^getCookie$',views.get_cookie),#獲取cookie頁
效果:
http://127.0.0.1:8000/setCookie
顯示:設置cookie
返回頭將看到:set-Cookie:name=jim; path=/
http://127.0.0.1:8000/getCookie
顯示jim,請求頭里有個信息即發送給服務器的cookieCookie:sessionid=5pvq8zmkgtb9omarod4q52lhfsmcc5sp; csrftoken=hW4qfF5faVmg60G1RRf7KCL8ZuwnA0OR7OqYpufJedQOGY3IZKaZmS6EXbLfbk8j; name=jim
關閉瀏覽器之后,再請求cookie即找不到之前設置的cookie,因為沒指定時間,所以用默認設置,關閉即過期:
http://127.0.0.1:8000/getCookie
3)設置cookie過期時間views.py
- 設置過期方式一 【max_age】(單位:秒):
max_age=14*24*3600
14天后過期 - 設置過期方式二 【expires】 (單位:時間):
expires=datetime.now()+timedelta(days=14)
14天后過期
from django.shortcuts import render,redirect
from django.http import HttpResponse,JsonResponse
from datetime import datetime,timedelta #【0】注意引入
# /set_cookie
def set_cookie(request):
'''設置cookie信息'''
response = HttpResponse('設置cookie')
# 設置一個cookie信息,名字為num, 值為1
# response.set_cookie('num2', 2)
response.set_cookie('num', 1, max_age=14*24*3600) #【1】14天后過期,單位,秒
# response.set_cookie('num', 1, expires=datetime.now()+timedelta(days=14)) #【2】即現在時間為准+14天后過期
# 返回response
return response
效果:http://127.0.0.1:8000/setCookie
再設置時會看到一個14天的日期
以后14天內這個cookie都會存在 。
4) 設置多個cookie
#1.設置cookie:/setCookie
def set_cookie(request):
'''請求設置cookie'''
response=HttpResponse('設置cookie')
response.set_cookie('name','jim',max_age=14*24*3600) #14天后過期
response=HttpResponse('設置cookie2')
response.set_cookie('age',20,max_age=15*24*3600) #14天后過期
return response
1.3 記住用戶名案例
1)templates/app1/login.html
【1】添加記住用戶名,設置cookie用,如果勾選則其value=on
【2】js添加是否記住用戶名
【3】js添加發送數據,加上remember
【4】把views頁的login()函數傳過來的用戶名,密碼賦值給對應處
用戶名:<input type="text" id="username" value="{{username}}"><br/>
密碼:<input type="password" id="password" value="{{password}}"><br/>
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<!-- 【0】引入jquery -->
<script src="/static/js/jquery-1.12.4.min.js"></script>
<title>登錄頁面</title>
</head>
<script>
// 寫ajax處理函數
$(function () {
$('#btnLogin').click(function () {
//1.獲取用戶名、密碼、是否記住用戶名
username=$('#username').val()
password=$('#password').val()
remember=$('#remember').val() //【2】是否記住用戶名
//2.發起ajax--post(username,password)請求驗證,地址:/login_check
$.ajax({
'url':'/login_check',//驗證地址
'type':'post',//請求類型
'data':{'username':username,'password':password,'remember':remember},//【3】發送數據,加上remember
'dataType':'json',//希望返回數據類型
}).success(function(data){
//成功返回{'res':1},失敗{'res':0}
if(data.res===0){
$('#msg').show().html('用戶名或密碼錯誤請重試!')//登錄失敗則顯示msg,並在里寫入信息
}else{//成功跳轉到books頁面
location.href='/books'
}
})
})
})
</script>
<style>
/* 信息提示樣式 */
#msg{
display: none;
color:red;
}
</style>
<body>
<!-- 原form刪除,input的name變id,方便jquery操作 -->
<!-- 【4】把views頁的login()函數傳過來的用戶名,密碼賦值給對應處 -->
用戶名:<input type="text" id="username" value="{{username}}"><br/>
密碼:<input type="password" id="password" value="{{password}}"><br/>
<!-- 加入一個信息提示框,用於密碼等錯誤提示 -->
<div id="msg"></div>
<!-- 【1】記住用戶名,設置cookie用,如果勾選則其value=on -->
<input type="checkbox" id="remember">記住用戶名<br/>
<!-- 按鈕type改button,加一個id方便jquery操作 -->
<input type="button" id="btnLogin" value="登錄">
</body>
</html>
2)app1/urls.py(不重要)
【1】登錄頁
【2】登錄檢測
from django.urls import path,re_path
from . import views
urlpatterns=[
path('login/',views.login),#【1】登錄頁
path('login_check',views.login_check),#【2】登錄檢測
re_path('^setCookie$',views.set_cookie),#設置cookie頁
re_path('^getCookie$',views.get_cookie),#獲取cookie頁
path('app1/',views.index),
path('books/',views.books),
# 書詳情頁,通過url接收參數2種寫法以下兩種都可:
# path(r"detail/<int:bookId>",views.detail), #參數用尖括號包起來<>
re_path(r"^detail/(\d+)",views.detail), #參數必須要帶括號
path('addInfo/',views.addInfo), #添加三國書
path(r'delete/<int:bid>',views.deleteInfo), #刪除對應圖書
path(r'areas/',views.areas), #展示對應省市區信息
path(r'test_ajax',views.test_ajax),#ajax測試頁
path(r'ajax_handle/',views.ajax_handle),#ajax測試頁
# re_path(r'^login_ajax', views.login_ajax), # 顯示ajax登錄頁面
# re_path(r'^login_ajax_check', views.login_ajax_check), # ajax登錄校驗
]
3)app1/views.py【重點】
【1】接收remeber
【2】正確返回1,重寫
【3】如果remember==on,則把用戶名,密碼設置cookie到cookie
【4】不要忘記返回response
【5】如果用戶名密碼已經在cookie中,則取到它,並做為參數返回給渲染頁面
[6]獲取cookie中的用戶名、密碼
from django.shortcuts import render,redirect #引入重定向簡寫模塊
from app1.models import BookInfo,AreaInfo #從模型下導入bookinfo數據模型
from django.http import HttpResponse,HttpResponseRedirect,JsonResponse #引入返回請求模塊、重新定向模塊
from datetime import datetime,timedelta # 引用時間模塊
def login(request):
'''登錄頁'''
#【5】如果用戶名密碼已經在cookie中,則取到它,並做為參數返回給渲染頁面
if 'username' in request.COOKIES:
#[6]獲取cookie中的用戶名、密碼
username=request.COOKIES['username']
password=request.COOKIES['password']
else:
username=''
password=''
return render(request,'app1/login.html',{'username':username,'password':password})
def login_check(request):
'''登錄校驗'''
#1.獲取用戶名密碼
username=request.POST.get('username')
password=request.POST.get('password')
remember=request.POST.get('remember') #【1】接收remeber
#2.進行校驗,並返回json數據
if username=='jim' and password=='123':
#return redirect('/books')
response = JsonResponse({'res':1}) #【2】正確返回1,重寫
#【3】如果remember==on,則把用戶名,密碼設置cookie到cookie
if remember=='on':
response.set_cookie('username',username,max_age=7*24*3600)
response.set_cookie('password',password,max_age=7*24*3600)
return response #【4】不要忘記返回response
else:
#return redirect('/login')
return JsonResponse({'res':0}) #錯誤返回0
效果 http://127.0.0.1:8000/login/
如果勾選上記住用戶名,提交時會讓/login_check處理,把用戶名、密碼的cookie設置到瀏覽器,
再次來到login頁面時,用戶名密碼會通過templates/login頁里的變量直接賦值到對應處,從而實現免填密碼登錄。
三、Session(存儲在服務器端)
session存儲在服務器端。
1 配置
啟用Session
Django項目默認啟用Session。
打開test3/settings.py文件,在項MIDDLEWARE_CLASSES中啟用Session中間件。
session中間件
禁用Session:將Session中間件刪除。
存儲方式
打開test3/settings.py文件,設置SESSION_ENGINE項指定Session數據存儲的方式,可以存儲在數據庫、緩存、Redis等。
1)存儲在數據庫中,如下設置可以寫,也可以不寫,這是默認存儲方式。
SESSION_ENGINE='django.contrib.sessions.backends.db'
2)存儲在緩存中:存儲在本機內存中,如果丟失則不能找回,比數據庫的方式讀寫更快。
SESSION_ENGINE='django.contrib.sessions.backends.cache'
3)混合存儲:優先從本機內存中存取,如果沒有則從數據庫中存取。
SESSION_ENGINE='django.contrib.sessions.backends.cached_db'
4)如果存儲在數據庫中,需要在項INSTALLED_APPS中安裝Session應用。
5)遷移后會在數據庫中創建出存儲Session的表。
存儲session
6)表結構如下圖。
存儲session表結構
由表結構可知,操作Session包括三個數據:鍵,值,過期時間。
2 使用方法:
1.設置:session:request.session['username']='jim'
2.獲取:session:request.session['username']
3.清除所有session,在存儲中刪除值部分。
request.session.clear()
4. 清除session數據,在存儲中刪除session的整條數據。
request.session.flush()
5. 刪除session中的指定鍵及值,在存儲中只刪除某個鍵及對應的值。
del request.session['鍵']
6.設置會話的超時時間,如果沒有指定過期時間則兩個星期后過期。
request.session.set_expiry(value)
- 如果value是一個整數,會話將在value秒沒有活動后過期。
- 如果value為0,那么用戶會話的Cookie將在用戶的瀏覽器關閉時過期。
- 如果value為None,那么會話永不過期。
3.1 session的特點:
- session是以鍵值對進行存儲的。
- session依賴於cookie。唯一的標識碼保存在sessionid cookie中。
- session也是有過期時間,如果不指定,默認兩周就會過期。
- 保存的是字符串,得到就是字符串,是數字,得到即數字。
- session保存位置:對應數據庫的表 django_session
3.2 session基本設置、獲取、清除案例
1)app1/views.py
設置session過期時間
#test /set_session
def set_session(request):
'''設置session'''
request.session['username'] = 'smart'
request.session['age'] = 18
# request.session.set_expiry(5) #設置session過期時間
return HttpResponse('設置session')
#test /get_session
def get_session(request):
'''獲取session'''
username = request.session['username']
age = request.session['age']
return HttpResponse(username+':'+str(age))
#test /clear_session
def clear_session(request):
'''清除session信息'''
# request.session.clear()
request.session.flush()
return HttpResponse('清除成功')
2)app1/urls.py
re_path('^setSession$',views.set_session),#設置session頁
re_path('^getSession$',views.get_session),#獲取session頁
re_path('^clearSession$',views.clear_session),#獲取session頁
效果 http://127.0.0.1:8000/setSession
http://127.0.0.1:8000/getSession
http://127.0.0.1:8000/clearSession
擴展:session的數據庫保存值是base64編碼
可在百度搜索 【base64解碼】,查看其保存具體信息
https://base64.supfree.net/
3.3 記住用戶登錄狀態案例
1)app1/views.py編寫登錄函數:設置session,讀取session
【1】如果用戶勾選了remember的條件下,設置session,記住用戶登錄狀態
【2】判斷用戶是否登錄,用戶已登錄, 直接跳轉到圖書列表
from django.shortcuts import render,redirect #引入重定向簡寫模塊
from app1.models import BookInfo,AreaInfo #從模型下導入bookinfo數據模型
from django.http import HttpResponse,HttpResponseRedirect,JsonResponse #引入返回請求模塊、重新定向模塊
from datetime import datetime,timedelta # 引用時間模塊
def login(request):
'''登錄頁'''
# 【2】判斷用戶是否登錄,用戶已登錄, 直接跳轉到圖書列表
if request.session.has_key('islogin'):
return redirect('/books')
else:
#如果用戶名密碼已經在cookie中,則取到它,並做為參數返回給渲染頁面
if 'username' in request.COOKIES:
#獲取cookie中的用戶名、密碼
username=request.COOKIES['username']
password=request.COOKIES['password']
else:
username=''
password=''
return render(request,'app1/login.html',{'username':username,'password':password})
def login_check(request):
'''登錄校驗'''
#1.獲取用戶名密碼
username=request.POST.get('username')
password=request.POST.get('password')
remember=request.POST.get('remember') #接收remeber
#2.進行校驗,並返回json數據
if username=='jim' and password=='123':
#return redirect('/books')
response = JsonResponse({'res':1}) #正確返回1,重寫
#如果remember==on,則把用戶名,密碼設置cookie到cookie
if remember=='on':
response.set_cookie('username',username,max_age=7*24*3600)
response.set_cookie('password',password,max_age=7*24*3600)
# 【1】如果用戶勾選了remember的條件下,設置session,記住用戶登錄狀態
request.session['islogin'] = True # 只有session中有islogin,就認為用戶已登錄
return response #不要忘記返回response
else:
#return redirect('/login')
return JsonResponse({'res':0}) #錯誤返回0
2)app1/urls.py
from django.urls import path,re_path
from . import views
urlpatterns=[
path('login/',views.login),#登錄頁
path('login_check',views.login_check),#登錄檢測
]
3)templates/app1/login.html
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<!-- 【0】引入jquery -->
<script src="/static/js/jquery-1.12.4.min.js"></script>
<title>登錄頁面</title>
</head>
<script>
// 寫ajax處理函數
$(function () {
$('#btnLogin').click(function () {
//1.獲取用戶名、密碼、是否記住用戶名
username=$('#username').val()
password=$('#password').val()
remember=$('#remember').val() //【2】是否記住用戶名
//2.發起ajax--post(username,password)請求驗證,地址:/login_check
$.ajax({
'url':'/login_check',//驗證地址
'type':'post',//請求類型
'data':{'username':username,'password':password,'remember':remember},//【3】發送數據,加上remember
'dataType':'json',//希望返回數據類型
}).success(function(data){
//成功返回{'res':1},失敗{'res':0}
if(data.res===0){
$('#msg').show().html('用戶名或密碼錯誤請重試!')//登錄失敗則顯示msg,並在里寫入信息
}else{//成功跳轉到books頁面
location.href='/books'
}
})
})
})
</script>
<style>
/* 信息提示樣式 */
#msg{
display: none;
color:red;
}
</style>
<body>
<!-- 原form刪除,input的name變id,方便jquery操作 -->
<!-- 【4】把views頁的login()函數傳過來的用戶名,密碼賦值給對應處 -->
用戶名:<input type="text" id="username" value="{{username}}"><br/>
密碼:<input type="password" id="password" value="{{password}}"><br/>
<!-- 加入一個信息提示框,用於密碼等錯誤提示 -->
<div id="msg"></div>
<!-- 【1】記住用戶名,設置cookie用,如果勾選則其value=on -->
<input type="checkbox" id="remember">記住用戶名<br/>
<!-- 按鈕type改button,加一個id方便jquery操作 -->
<input type="button" id="btnLogin" value="登錄">
</body>
</html>
效果:http://127.0.0.1:8000/login
- 第一次登錄勾選記住用戶名密碼后
- 再訪問登錄頁時,將自動跳轉到:http://127.0.0.1:8000/books
3.4 cookie和session的應用場景
- cookie:記住用戶名。安全性要求不高。
- session:涉及到安全性要求比較高的數據。銀行卡賬戶,密碼