如何通过Django的_request.session在用户会话中存取数据?

2026-05-07 11:541阅读0评论SEO基础
  • 内容介绍
  • 文章标签
  • 相关推荐

本文共计824个文字,预计阅读时间需要4分钟。

如何通过Django的_request.session在用户会话中存取数据?

直接赋值或读取字典式键值就执行,Django 自动处理序列化、签名、存储和过期。无需手动调用 save(),除非禁用了 SESSION_SAVE_EVERY_REQUEST 且未修改 session 内容。

  • request.session['user_id'] = 123 —— 写入后下次请求就能读到
  • uid = request.session.get('user_id') —— 推荐用 get(),避免 KeyError
  • del request.session['user_id']request.session.pop('user_id', None) —— 删除要显式操作
  • 存非 JSON 序列化类型(如 datetime、自定义类)会报 PickleError,只建议存基础类型(strintdictlistbool

为什么 request.session 有时读不到刚写的数据

常见于重定向场景:写完 session 立即 redirect(),但响应还没发 cookie,浏览器下个请求就带不上新 sessionid —— Django 默认延迟写入 cookie,直到响应头真正发出。

  • 确保视图返回的是 HttpResponse 或其子类(比如 redirect() 返回的 HttpResponseRedirect 是 OK 的)
  • 不要在中间件或信号里提前读写 session,容易因执行时机错乱导致读空
  • 如果用了 request.session.modified = True 强制标记已改,注意它不触发写入,只是影响是否发送 session cookie
  • 调试时检查响应头有没有 Set-Cookie: sessionid=...,没有说明 session 没真正提交

request.session 和数据库、缓存后端的关系

session 数据存在哪,取决于 SESSION_ENGINE 设置,默认是 django.contrib.sessions.backends.db,也就是每读写都查一次数据库 —— 并不慢,但高并发下可能成瓶颈。

  • 想用 Redis?装 django-redis,设 SESSION_ENGINE = 'django.contrib.sessions.backends.cache''django.contrib.sessions.backends.cached_db'
  • cached_db 是推荐折中:读走 cache,写双写 cache + db,断电也不丢数据
  • 改后端不影响代码,request.session API 完全不变
  • 注意:cache 模式下 session 可能被 LRU 清掉,用户莫名登出;db 模式下记得定期运行 python manage.py clearsessions

哪些值不能往 request.session 里塞

不是所有 Python 对象都能存。Django session 序列化默认用 pickle(db 后端)或 JSON(cache 后端),但即使启用了 pickle,也强烈不建议存复杂对象。

  • 模型实例(User 对象)—— 会 pickle 成二进制,反序列化可能失败,且含敏感字段
  • 文件句柄、线程锁、socket 连接等运行时资源 —— 下次请求根本无法还原
  • lambda、嵌套函数、本地作用域闭包 —— pickle 不支持
  • 正确做法:只存 ID(如 request.session['user_id'] = user.id),需要时再查库

session 不是临时数据库,它只该存轻量、可预测、可丢弃的状态标识。真要传复杂结构,先转成 dict/list,再确认能被 JSON.dumps() 过。

标签:django

本文共计824个文字,预计阅读时间需要4分钟。

如何通过Django的_request.session在用户会话中存取数据?

直接赋值或读取字典式键值就执行,Django 自动处理序列化、签名、存储和过期。无需手动调用 save(),除非禁用了 SESSION_SAVE_EVERY_REQUEST 且未修改 session 内容。

  • request.session['user_id'] = 123 —— 写入后下次请求就能读到
  • uid = request.session.get('user_id') —— 推荐用 get(),避免 KeyError
  • del request.session['user_id']request.session.pop('user_id', None) —— 删除要显式操作
  • 存非 JSON 序列化类型(如 datetime、自定义类)会报 PickleError,只建议存基础类型(strintdictlistbool

为什么 request.session 有时读不到刚写的数据

常见于重定向场景:写完 session 立即 redirect(),但响应还没发 cookie,浏览器下个请求就带不上新 sessionid —— Django 默认延迟写入 cookie,直到响应头真正发出。

  • 确保视图返回的是 HttpResponse 或其子类(比如 redirect() 返回的 HttpResponseRedirect 是 OK 的)
  • 不要在中间件或信号里提前读写 session,容易因执行时机错乱导致读空
  • 如果用了 request.session.modified = True 强制标记已改,注意它不触发写入,只是影响是否发送 session cookie
  • 调试时检查响应头有没有 Set-Cookie: sessionid=...,没有说明 session 没真正提交

request.session 和数据库、缓存后端的关系

session 数据存在哪,取决于 SESSION_ENGINE 设置,默认是 django.contrib.sessions.backends.db,也就是每读写都查一次数据库 —— 并不慢,但高并发下可能成瓶颈。

  • 想用 Redis?装 django-redis,设 SESSION_ENGINE = 'django.contrib.sessions.backends.cache''django.contrib.sessions.backends.cached_db'
  • cached_db 是推荐折中:读走 cache,写双写 cache + db,断电也不丢数据
  • 改后端不影响代码,request.session API 完全不变
  • 注意:cache 模式下 session 可能被 LRU 清掉,用户莫名登出;db 模式下记得定期运行 python manage.py clearsessions

哪些值不能往 request.session 里塞

不是所有 Python 对象都能存。Django session 序列化默认用 pickle(db 后端)或 JSON(cache 后端),但即使启用了 pickle,也强烈不建议存复杂对象。

  • 模型实例(User 对象)—— 会 pickle 成二进制,反序列化可能失败,且含敏感字段
  • 文件句柄、线程锁、socket 连接等运行时资源 —— 下次请求根本无法还原
  • lambda、嵌套函数、本地作用域闭包 —— pickle 不支持
  • 正确做法:只存 ID(如 request.session['user_id'] = user.id),需要时再查库

session 不是临时数据库,它只该存轻量、可预测、可丢弃的状态标识。真要传复杂结构,先转成 dict/list,再确认能被 JSON.dumps() 过。

标签:django