You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Django 3.2如何在视图内外函数中获取用户ID实现专属缓存?

在Django 3.2中实现请求周期内全局获取用户ID的方案

可以通过**线程本地存储(threading.local)**结合Django中间件实现请求周期内全局获取用户ID,完全不需要修改现有函数的参数。如果你的项目用到异步视图,也可以改用contextvars适配协程环境,以下是具体实现步骤:

1. 编写请求上下文工具模块

创建工具文件(比如utils/request_context.py),用来存储和获取当前请求的用户:

import threading

# 线程本地存储,每个请求线程独立持有数据
_local = threading.local()

def set_current_user(user):
    """设置当前请求的用户"""
    _local.user = user

def get_current_user_id():
    """获取当前请求用户的ID,未登录则返回None"""
    user = getattr(_local, 'user', None)
    return user.id if user else None

如果项目包含异步视图,改用contextvars(Django 3.2支持)适配协程:

import contextvars

# 协程上下文变量,每个协程独立持有数据
current_user = contextvars.ContextVar('current_user', default=None)

def set_current_user(user):
    current_user.set(user)

def get_current_user_id():
    user = current_user.get()
    return user.id if user else None

2. 实现中间件注入用户信息

创建中间件文件(比如middleware.py),在请求进入时自动设置当前用户:

from django.utils.deprecation import MiddlewareMixin
from .utils.request_context import set_current_user

class CurrentUserMiddleware(MiddlewareMixin):
    def process_request(self, request):
        # 仅在用户已认证时设置,未登录则设为None
        if request.user.is_authenticated:
            set_current_user(request.user)
        else:
            set_current_user(None)

    # 兼容异步视图的处理
    async def __call__(self, request):
        if request.user.is_authenticated:
            set_current_user(request.user)
        else:
            set_current_user(None)
        response = await self.get_response(request)
        return response

然后在settings.py的MIDDLEWARE列表中添加该中间件,必须放在AuthenticationMiddleware之后,确保request.user已被正确认证:

MIDDLEWARE = [
    # 其他中间件...
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'your_app_name.middleware.CurrentUserMiddleware',  # 替换为你的应用名
    # 其他中间件...
]

3. 在缓存中使用用户ID

现在你可以在任何函数(包括视图外的工具函数)中直接调用get_current_user_id(),结合django-cache-memoize生成用户专属的缓存键:

from cache_memoize import cache_memoize
from .utils.request_context import get_current_user_id

# 生成带用户ID的缓存前缀,确保每个用户的缓存独立
@cache_memoize(3600, key_prefix=lambda: f"user_{get_current_user_id()}")
def fetch_user_specific_data():
    # 这里返回用户专属的业务数据
    return some_database_query()

注意事项

  • 未登录用户:get_current_user_id()会返回None,此时可根据需求决定是否缓存(比如给未登录用户设置固定前缀,或者跳过缓存)。
  • 线程/协程安全:线程本地存储和contextvars都是当前请求上下文隔离的,不会出现多请求数据混乱的问题。
  • 缓存键唯一性:通过user_{user_id}作为前缀,确保每个用户的缓存键完全独立,不会互相覆盖。

内容的提问来源于stack exchange,提问作者thisisnotatest

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.21 19:28:18