Django之session操作(十)
一、Session介绍
1.1 session机制
session机制是一种服务器端的机制,服务器使用一种类似于散列表的结构(也可能就是使用散列表)来保存信息。
当程序需要为某个客户端的请求创建一个session的时候,服务器首先检查这个客户端的请求里是否已包含了一个session标识 - 称为session id,如果已包含一个session id则说明以前已经为此客户端创建过session,服务器就按照session id把这个session检索出来使用(如果检索不到,可能会新建一个),如果客户端请求不包含session id,则为此客户端创建一个session并且生成一个与此session相关联的session id,session id的值应该是一个既不会重复,又不容易被找到规律以仿造的字符串,这个session id将被在本次响应中返回给客户端保存。
在谈论session机制的时候,常常听到这样一种误解“只要关闭浏览器,session就消失了”。其实可以想象一下会员卡的例子,除非顾客主动对店家提出销卡,否则店家绝对不会轻易删除顾客的资料。对session来说也是一样的,除非程序通知服务器删除一个session,否则服务器会一直保留,程序一般都是在用户做log off的时候发个指令去删除session。然而浏览器从来不会主动在关闭之前通知服务器它将要关闭,因此服务器根本不会有机会知道浏览器已经关闭,之所以会有这种错觉,是大部分session机制都使用会话cookie来保存session id,而关闭浏览器后这个session id就消失了,再次连接服务器时也就无法找到原来的session。如果服务器设置的cookie被保存到硬盘上,或者使用某种手段改写浏览器发出的HTTP请求头,把原来的session id发送给服务器,则再次打开浏览器仍然能够找到原来的session。
恰恰是由于关闭浏览器不会导致session被删除,迫使服务器为seesion设置了一个失效时间,当距离客户端上一次使用session的时间超过这个失效时间时,服务器就可以认为客户端已经停止了活动,才会把session删除以节省存储空间。
session服务端中存在的数据为:
session = { 随机字符串1:{ 用户1的相关信息 } 随机字符串2:{ 用户2的相关信息 } } #session客户端即客户端的浏览器的cookie中存的数据是当前用户对应的随机字符串
http://justsee.iteye.com/blog/1570652 #介绍的很详细
1.2 session的工作过程
session的工作过程为:
生成随机字符串
写到用户浏览器的cookie中
保存到session中
在随机字符串对应的字典中设置相关内容
而在django中,request.session['username'] = user 就会把需要的四步骤都给做了。
注意的是:
如果想用session的功能呢 先要创建对应的数据库表。所以在Django中要用session中一定要先执行:
python manage.py makemigrations
python manage.py migrate
1.3 session的使用:
def index(request): # 获取、设置、删除Session中数据 request.session['k1'] #里面已经包含了 request.session.exists,所以 request.session.exists用不到。 request.session.get('k1',None) #和上面的区别是第一条是如果取不到就报错,第二个是取不到返回一个None。 request.session['k1'] = 123 request.session.setdefault('k1',123) #上面两条的区别是,第一条是不存在就创建存在就更新,下面这条存在则不设置 del request.session['k1'] #删除当前用户session里面的某一键值给删掉了 # 所有 键、值、键值对 request.session.keys() request.session.values() request.session.items() request.session.iterkeys() request.session.itervalues() request.session.iteritems() #上面就是对字典进行循环 #用户session的随机字符串 request.session.session_key # 将所有Session失效日期小于当前日期的数据删除 request.session.clear_expired() #数据库里面旧的记录不会自动删除就是脏数据了所以这样执行一下,不过缓存里面又自动删除过期数据的机制。 # 检查 用户session的随机字符串 在数据库中是否 request.session.exists("session_key") # 删除当前用户的所有Session数据 request.session.delete("session_key") request.session.clear() #这个点注销的时候用 request.session.set_expiry(value) * 如果value是个整数,session会在些秒数后失效。也可以(60*60) * 如果value是个datatime或timedelta,session就会在这个时间后失效。 * 如果value是0,用户关闭浏览器session就会失效。 * 如果value是None,session会依赖全局session失效策略。 #django的session失效时间默认是2周。如果不想走默认就是上面的设置。
1.4 django里面的默认设置,如果要修改需要配置settings.py
SESSION_ENGINE = 'django.contrib.sessions.backends.db' #引擎(默认) SESSION_COOKIE_NAME = "sessionid" #Session的cookie保存在浏览器上时的key,即:sessionid=随机字符串(默认) SESSION_COOKIE_PATH = "/" #Session的cookie保存的路径(默认) SESSION_COOKIE_DOMAIN = None #Session的cookie保存的域名(默认) SESSION_COOKIE_SECURE = False #是否Https传输cookie(默认) SESSION_COOKIE_HTTPONLY = True #是否Session的cookie只支持http传输(默认) SESSION_COOKIE_AGE = 1209600 #Session的cookie失效日期(2周)(默认) SESSION_EXPIRE_AT_BROWSER_CLOSE = False #是否关闭浏览器使得Session过期(默认) SESSION_SAVE_EVERY_REQUEST = False #是否每次请求都保存Session,默认修改之后才保存(默认)#如果这里改为True,就变成了最后一次操作的超时时间而不是登录开始计算超时时间。
1.5 Django中对于session的存储方式
Django中默认支持Session,其内部提供了5种类型的Session供开发者使用:
数据库(默认)
缓存
文件
缓存+数据库
加密cookie
缓存session
#配置 settings.py SESSION_ENGINE = 'django.contrib.sessions.backends.cache' #引擎 SESSION_CACHE_ALIAS = 'default' #使用的缓存别名(默认内存缓存,也可以是memcache),此处别名依赖缓存的设置
文件Session
SESSION_ENGINE = 'django.contrib.sessions.backends.file' #引擎
SESSION_FILE_PATH = None #缓存文件路径,如果为None,则使用tempfile模块获取一个临时地址tempfile.gettempdir() # 如:/var/folders/d3/j9tj0gz93dg06bmwxmhh6_xm0000gn/T
缓存+数据库Session
#数据库用于做持久化,缓存用于提高效率 SESSION_ENGINE = 'django.contrib.sessions.backends.cached_db' #引擎
加密cookie Session
SESSION_ENGINE = 'django.contrib.sessions.backends.signed_cookies' #引擎
二、来点例子
2.1 做一个基于session做用户登录:
python manage.py makemigrations
python manage.py migrate
#先把上面两步操作做了
views.py:
from django.shortcuts import render,redirect,HttpResponse # Create your views here. def login(request): if request.method == "GET": return render(request,'login.html') elif request.method == "POST": user = request.POST.get('user') pwd = request.POST.get('pwd') if user == 'root' and pwd == "123": # session中设置值 #生成随机字符串、写到用户浏览器cookie、保存到session中、在随机字符串对应的字典中设置相关内容 request.session['username'] = user #上面一句话django就会把需要的四步骤都给做了,首先表示在本地浏览器会生成随机字符串,会在服务器端生成对应的username对应的键值对。 request.session['is_login'] = True #表示登录成功 return redirect('/index/') else: return render(request,'login.html') def index(request): # session中获取值 #获取当前用户的随机字符串,根据随机字符串获取对应信息 if request.session['is_login']: return HttpResponse(request.session['username']) else: return HttpResponse('gun')
login.html :
<body> <form action="/login/" method="POST"> <input type="text" name="user" /> <input type="text" name="pwd" /> <input type="submit" value="提交" /> </form> </body>
index.html :
<body> <p>欢迎登陆:{{ username }}</p> </body
登录测试:
#上面这个随机字符串给浏览器一个,默认在后台mysql数据库里面也有一个。
#session_key是发给客户端的key也就相当于存在字典里,面的keysession_data就相当于对用户名进行的一个随机加密字符串,本质就是一个username = root
2.2 再来个注销的小例子
views.py:
def index(request): # session中获取值 #if request.session['is_login']: if request.session.get('is_login',None): #这里是防止注销后拿不到数据报错 return render(request,'index.html',{'username':request.session['username']}) #{'username':request.session['username']}这个可传可不传,request里面已经把内容全放到前端了 else: return HttpResponse('gun') def logout(request): #del request.session['username'] request.session.clear() return redirect('/login/')
index.html:
<body> <p>欢迎登陆:{{ username }},{{ request.session.username }}</p> <a href="/logout/">注销</a> </body>