一、启用Session
Django项目默认启用Session。
可以在settings.py文件中查看,如图所示
如需禁用session,将上图中的session中间件注释掉即可。
二、 存储方式
在settings.py文件中,可以设置session数据的存储方式,可以保存在数据库、本地缓存等。
1、存在在默认数据库中
默认存储在数据库中,如下设置可以写,也可以不写,这是默认存储方式。
SESSION_ENGINE='django.contrib.sessions.backends.db'
django.contrib.sessions.backends.db
会使用DATABASES 设置的数据库,例如
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql', # 连接数据库的类型
'NAME': 'luckybaseline', # 数据库名
'HOST': '127.0.0.1', # 数据库主机
'PORT': 3306,
"USER": 'root',
'PASSWORD': '123456',
}
}
数据库中会创建django_session这个表
表结构如下,包括三个数据:键,值,过期时间
2、本地缓存
存储在本机内存中,如果丢失则不能找回,比数据库的方式读写更快。
SESSION_ENGINE='django.contrib.sessions.backends.cache'
3 混合存储
优先从缓存中存取,如果没有则从数据库中存取。
SESSION_ENGINE='django.contrib.sessions.backends.cached_db'
4、redis 缓存
在settings.py文件中SESSION_ENGINE
开启缓存,并设置CACHES
地址为redis
SESSION_ENGINE = "django.contrib.sessions.backends.cache"
CACHES = {
"default": {
"BACKEND": "django_redis.cache.RedisCache",
"LOCATION": "redis://127.0.0.1:6379/1",
"OPTIONS": {
"CLIENT_CLASS": "django_redis.client.DefaultClient",
}
}
}
SESSION_CACHE_ALIAS = "default"
三、Session操作
通过HttpRequest对象的session属性进行会话的读写操作。
1、以键值对的格式写session。
request.session['键']=值
2、根据键读取值。
request.session.get('键',默认值)
3、清除所有session,在存储中删除值部分。
request.session.clear()
4、清除session数据,在存储中删除session的整条数据。
request.session.flush()
5、删除session中的指定键及值,在存储中只删除某个键及对应的值。
del request.session['键']
6、设置session的有效期
request.session.set_expiry(value)
- 如果value是一个整数,session将在value秒没有活动后过期。
- 如果value为0,那么用户session的Cookie将在用户的浏览器关闭时过期。
- 如果value为None,那么session有效期将采用系统默认值,默认为两周,可以通过在settings.py中设置SESSION_COOKIE_AGE来设置全局默认值。
# COOKIE过期时间设为30天
SESSION_COOKIE_AGE = 60 * 60 * 24 * 30
四、实践
1、缓存设置,我这里使用混合存储优先从redis中取
SESSION_ENGINE = "django.contrib.sessions.backends.cache"
CACHES = {
"default": {
"BACKEND": "django_redis.cache.RedisCache",
"LOCATION": "redis://127.0.0.1:6379/1",
"OPTIONS": {
"CLIENT_CLASS": "django_redis.client.DefaultClient",
}
}
}
SESSION_CACHE_ALIAS = "default"
2、用户登录创建session
首先访问登陆的接口,使用session的前提是用户有进行登陆,接口里调用django的login函数会为用户创建session。这里登陆接口不再描述。
# 如果认证成功,判断user表中是否存在该用户
user = User.objects.filter(username=email)
# 如果用户存在,则设置session
if user.exists():
login(request, user[0])
查看redis中有为用户创建key
查看mysql中django_session表中为用户创建了一条新的记录
说明设置混合存储后,session会同时写到redis和mysql中。
3、用户登出注销session
登出调用django的logout函数
#登陆示例
def post(self,request):
username= request.user.username
#print(username)
logout(request)
return Response({"message":"退出成功","username":username},status=status.HTTP_200_OK)
查看redis,刚才那个key已经没了
查看mysql,刚才那条记录也没了
说明设置混合存储后,session删除会同时到redis和mysql中删除。
4、自定义session内容
定义get post delete三个接口来定义session
class TestSessionAPIView(APIView):
def get(self,request):
print(request.session.get("testsession"))
return Response(request.session.get("testsession"))
def post(self,request):
request.session['testsession']="23333"
return Response("post test interface")
def delete(self,request):
del request.session["testsession"]
return Response("delete test interface")
首先请求post接口,创建session的testsession这个key值
然后请求get接口,获取session的key值
然后调用delete接口,删除刚才创建的key值
再获取就获取不到了
五、存储优先级测试
1、登陆并创建key
首先进行登陆生成用户的session,然后调用上面的post接口创建testsession这个key,这个时候redis和mysql中都有存储session。
2、将redis中该用户的session删除
127.0.0.1:6379> key *
(error) ERR unknown command `key`, with args beginning with: `*`,
127.0.0.1:6379> keys *
1) "_kombu.binding.celeryev"
2) "_kombu.binding.default"
3) ":1:django.contrib.sessions.cacheavh5lzcneh0ydg5k97lsqykfpn90oaoy"
4) "_kombu.binding.celery"
5) "_kombu.binding.app_task1"
6) ":1:django.contrib.sessions.cached_dbp6i3ex1tgup92m8tdwptvvhuaq22stlb"
7) "_kombu.binding.app_task2"
8) "_kombu.binding.celery.pidbox"
127.0.0.1:6379> del :1:django.contrib.sessions.cached_dbp6i3ex1tgup92m8tdwptvvhuaq22stlb
(integer) 1
127.0.0.1:6379> get :1:django.contrib.sessions.cached_dbp6i3ex1tgup92m8tdwptvvhuaq22stlb
(nil)
然后再访问get接口,获取testsession这个key值,可以获取到,并且redis中的session数据又重新生成了。
说明当redis缓存中没有session时,会到mysql中获取,如果获取到了,还会将session重新写入到redis缓存中。
3、将mysql中session删除
现在先将mysql中的session删除
然后调用get获取key值,可以获取到
但是查看mysql中的session信息并没有重新写入,说明是先读取的redis缓存中的session信息,如果读取到了则直接返回,不会再去验证mysql中的。
然后再调用post接口设置key,报错了,查看后台报错,提示用户请求的session已经被删除了,这个用户可能已经登出了。
而查看redis中的数据并没有变化,说明在写入是可能是先写入到mysql,再写入redis缓存,如果mysql报错了则直接返回了,不会再写入redis。
综上所述,使用混合缓存是,mysql中的数据是很重要的,如果删除或损坏了,session可能就无法恢复了