blog
blog copied to clipboard
Django Cookies and Session
参考:📖 Django文档-如何使用会话:https://docs.djangoproject.com/zh-hans/3.1/topics/http/sessions/
一、Django操作Cookies
参考:🎬Day69-05 django操作cookie:https://www.bilibili.com/video/BV1Sp4y1U7Jr?p=792 第13分钟
简单需求:简易管理员登录表单,需要获取Cookies(登录状态)后才能访问管理后台页面,直接访问管理后台页面URL(没有获得Cookies)无效并自动跳转回登录页面:
def login(request):
if request.method == 'POST':
username = request.POST.get('username')
password = request.POST.get('password')
if username == 'root' and password == 'root123':
# return redirect('/admin/')
# 保存用户登录状态:
obj = redirect('/admin/')
# 让浏览器记录Cookies数据。设置过期时间为3秒(可选),expires参数针对IE浏览器起作用
obj.set_cookie('is_allow_to_next_page', 'true', max_age=3, expires=3)
# 跳转到一个需要管理员登录后,才能看到的页面
return obj
return render(request, 'login.html')
def admin(request):
# 获取cookie信息(从登录页面保存过来的)
if request.COOKIES.get('username') == 'root':
return HttpResponse('这是admin页面,只有登录的用户才能查看')
return redirect('/login/')
二、Django操作Session
参考:📖如何使用会话:https://docs.djangoproject.com/zh-hans/3.1/topics/http/sessions/
参考:🎬Day69-06 session操作:https://www.bilibili.com/video/BV1Sp4y1U7Jr?p=793
2.1 设置Session
def set_session(request):
""" `requset.session['key'] = value` 这行代码的作用:
1. Django内部自动生成一个随机字符串(django_session表中的session_key,浏览器Cookies中sessionid对应的Value)
2. Django内部自动将随机字符串(session_key)和对应的数据存储到django_session表中
2.1. 先在内存中产生操作数据库的缓存
2.2 在响应经过Django中间件(django.contrib.sessions.middleware.SessionMiddleware)的时候,才真正操作数据库
3. 将(服务器)产生的随机字符串(session_key)返回给(客户端)浏览器保存(Cookies中sessionid对应的Value)
"""
request.session['hobby'] = 'coding'
return HttpResponse('设置Session成功!')
def get_sesssion(request):
""" `request.session.get('key')` 这行代码的作用:
1. 自动从浏览器请求中获取sessionid对应的随机字符串
2. 拿着该随机字符串去django_session表中查找对应的数据(存储在django_session表中的session_data:包含编码encode和序列化会话字典的字符串)
3. 如果查找到对应的数据(session_data),则将对应的数据取出,并以字典的形式封装到request.session中;如果查找不到对应的数据,则request.session.get('key')返回None
"""
print(request.session.get('hobby'))
return HttpResponse('获取Session成功!')
2.2 django_session表中,一个浏览器只会有一条对应的(未过期)session记录
在同一台计算机上的同一个浏览器上操作,即使设置了多个 session 键值对,例如:
def set_session(request):
request.session['hobby'] = 'coding'
requset.session['hobby02'] = 'basketball'
requset.session['hobby03'] = 'travel'
return HttpResponse('设置Session成功!')
django_session 表中只会有一条对应的记录,而不会产生多条记录对应同一个浏览器(除非对应该浏览器的session记录过期了,会重新生成一条新的记录对应同一个浏览器)。
⚠️ 注意:假设此时 django_session 表中因为用户登录而产生了一条 session 记录,此时执行以上代码新增了 3 个 session 数据: django_session 表的这条记录中的 session_key
字段(对应浏览器 Cookies 中 sessionid 的值)不会改变,但是这条记录中 session_data
(包含编码encode和序列化会话字典的字符串)字段将会发生更新。
2.3 设置Session过期时间
Django 默认的 Session 过期时间是 14 天。
2.3.1 在settings.py中设置Session过期时间
# 设置每次请求都保存Session(更新django_session表记录中的的expire_date),默认值为False。
# 参考:https://docs.djangoproject.com/zh-hans/3.1/topics/http/sessions/#when-sessions-are-saved
SESSION_SAVE_EVERY_REQUEST = True
# 设置session过期时间(默认登录状态过期失效为14天)
# 参考:https://docs.djangoproject.com/zh-hans/3.1/topics/http/sessions/#browser-length-sessions-vs-persistent-sessions
# SESSION_COOKIE_AGE = 1209600 # 1209600 seconds(2 weeks)
SESSION_COOKIE_AGE = 60*60*24*365 # 365 days, refer to instagram.com
2.3.2 在视图函数中设置Session过期时间
参考:https://docs.djangoproject.com/zh-hans/3.1/topics/http/sessions/#django.contrib.sessions.backends.base.SessionBase.set_expiry
def set_session(request):
""" `request.session.set_expiry()` 括号内可以放4种类型的参数:
1. 整数:多少秒后过期失效
2. 日期对象:到指定日期就过期失效
3. 0:当前浏览器关闭后就过期失效
4. 不写:使用Django默认的session过期失效时间(14天)
"""
# 设置session过期时间为10秒
# 此时访问该视图,settings.py中设置的SESSION_COOKIE_AGE配置将会无效。
# 此时不是访问该视图(如访问Django默认的登录视图),session过期时间则为SESSION_COOKIE_AGE配置的值。
# 如果访问了Django默认的登录视图后,再访问该视图,并且此时session未过期,django_session表中expire_date的值将由SESSION_COOKIE_AGE配置的值更新为该视图设置的10秒后过期。如果此时session记录已经过期,则会新增一条session记录。
request.session.set_expiry(10)
request.session['hobby'] = 'coding'
return HttpResponse('设置Session成功!')
def get_session(request):
if request.session.get('hobby'):
print(request.session.get('hobby'))
return HttpResponse('获取Session成功!')
return HttpResponse('获取Session(hobby的值)失败!')
2.4 删除session记录
参考:📖 flush():https://docs.djangoproject.com/zh-hans/3.1/topics/http/sessions/#django.contrib.sessions.backends.base.SessionBase.flush
参考:📖 clearsessions:https://docs.djangoproject.com/zh-hans/3.1/topics/http/sessions/#clearing-the-session-store
flush():
request.session.flush()
:删除当前会话和会话cookie,即服务器 django_session 表和客户的浏览器的Cookies 中的 sessionid 记录。如果你想确保早先的会话数据不能被用户的浏览器再次访问时,可以使用这个方法(比如,django.contrib.auth.logout()
函数调用它)。
也就是说,用户 logout ,会删除django_session中对应的(未过期的)记录。
clearsessions:
但是,Django 没有提供过期会话自动清除的功能。也就是说,如果 django_session 表中对应的记录已经过期,此时即使用户 logout,也无法删除该记录了。
因此,你需要定期清除过期会话。Django 提供了一个清除管理命令:clearsessions
。推荐在定期清除时使用该命令,例如在日常的定时任务中。或命令行中手动执行:$ python manage.py clearsessions
。