python_django_在views模块中操作状态保持(session)
什么叫状态保持?
就比如说我们登陆一个网站,登陆之后的当前页面显示的是登陆状态,但是我们要再跳转同一网站的其他页面,则显示的未登录状态,状态保持就是:我们在当前页面登陆后,再访问其他页面时也显示为登陆状态,这就是状态保持
为什么会出现状态不保持?
因为我们http协议是无状态的,它每一次请求都是一个新的请求。在服务器和客户端建立连接后,服务器与客户端的每一次会话都是一次http协议(客户端发送请求与服务器对请求的响应)的体现。
为什么要进行状态保持?
在一段时间内跟踪请求者的状态,实现跨页面访问当前的请求者数据。并且不同的请求者之间不会共享这个数据,与登陆的请求者是一一对应的。
如何实现状态保持?
我们可以在客户端或者服务端把有关会话的数据存储起来。
状态保持的存储方式:
- cookie: 所有的数据都存储在客户端(可以使用cookie存储方式,但不要存重要或敏感的数据,因为cookie不安全,并且可以存储的数据量也不大)
- session:所有数据都存储在服务器端,并在客户端利用cookie存储session_id(相当于去服务器端拿数据的钥匙key),服务器端拿到session_id 就会去数据库匹配对应的value数据值并返回。
【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的随机字符串是否在数据库中 |
举个栗子:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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文件:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<!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>
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<!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()并存储,也可设置地址 |