一、缓存基础与环境准备
什么是缓存?
缓存是指保存计算密集型操作的结果,当再次需要该结果时直接从缓存中获取,而无需重新计算。在 Django 中,缓存可以应用于不同粒度:
- 整个网站缓存
- 特定视图缓存
- 页面片段缓存
- 任意 Python 对象缓存
安装Redis
Django 支持多种缓存后端,其中 Redis 因其高性能和丰富的特性成为常用选择。
Redis 缓存配置
在 Django 项目的settings.py文件中,通过CACHES配置项设置 Redis 缓存后端。
- TIMEOUT:默认缓存超时时间(秒),默认为 300 秒(5 分钟)
- OPTIONS:传递给缓存后端的选项
- KEY_PREFIX:所有缓存键的前缀字符串
- VERSION:缓存键的默认版本号
- KEY_FUNCTION:定义缓存键生成规则的函数路径
- CACHES = {
- "default": {
- "BACKEND": "django.core.cache.backends.redis.RedisCache",
- "LOCATION": "redis://password@127.0.0.1:6379",
- "OPTIONS": {
- "db": 0,
- },
- "KEY_PREFIX": "mars_framework", # 缓存前缀
- "TIMEOUT": 60 * 60 * 12, # 缓存过期时间,单位为秒
- }
- }
复制代码 二、缓存使用策略
站点缓存(不常用)
缓存整个站点是最简单的缓存方式,适用于内容不常变化的网站。配置方式如下(在settings.py的MIDDLEWARE中添加缓存中间件)- MIDDLEWARE = [
- 'django.middleware.cache.UpdateCacheMiddleware', # 放在最前面
- # 其他中间件...
- 'django.middleware.cache.FetchFromCacheMiddleware', # 放在最后面
- ]
复制代码 视图缓存
针对特定视图进行缓存是更灵活的方式,适用于不同视图有不同更新频率的场景。
使用装饰器缓存视图- from django.views.decorators.cache import cache_page
- @cache_page(60 * 15) # 缓存15分钟
- def my_view(request):
- # 视图逻辑...
复制代码 视图缓存的特点
- 以 URL 为缓存键,不同 URL 指向同一视图会分别缓存
- 示例:/foo/1/和/foo/23/会被分别缓存
- urlpatterns = [
- path("foo/<int:code>/", my_view),
- ]
复制代码 自定义缓存前缀:可以为不同视图设置不同的缓存前缀- @cache_page(60 * 15, key_prefix="site1")
- def my_view(request):
- ...
复制代码 在 URLconf 中配置缓存- from django.views.decorators.cache import cache_page
- urlpatterns = [
- path("foo/<int:code>/", cache_page(60 * 15)(my_view)),
- ]
复制代码 三、缓存API详解
当需要更精细的缓存控制时,可以使用 Django 提供的缓存 API,直接操作缓存中的数据。
导入缓存模块
- from django.core.cache import cache
复制代码 基本操作
设置缓存- # 语法:cache.set(key, value, timeout=默认超时, version=None)
- cache.set('my_key', 'hello, world!', 30) # 缓存30秒
复制代码 获取缓存- # 语法:cache.get(key, default=None, version=None)
- value = cache.get('my_key') # 获取缓存值,如果不存在返回None
- value = cache.get('my_key', 'default_value') # 指定默认值
复制代码 新增缓存(仅当键不存在时)- # 如果键不存在则添加,返回布尔值表示是否成功
- success = cache.add("add_key", "Initial value")
复制代码 获取或设置缓存- # 如果键存在则获取,否则设置并返回默认值
- value = cache.get_or_set("my_new_key", "my new value", 100)
复制代码 删除缓存- # 删除指定键,返回布尔值表示是否成功
- success = cache.delete("a")
复制代码 更新缓存过期时间- # 为已有键设置新的过期时间
- success = cache.touch("a", 10) # 新超时时间10秒
复制代码 四、缓存实战
场景说明
RBAC(Role-Based Access Control,基于角色的访问控制)是一种广泛使用的权限管理模型。在 Django+Vue 实现的后台管理系统中,一般采用RBAC权限策略。使用缓存机制,避免重复计算用户权限标识集合。
写入缓存
用户成功登录后,前端自动调用获取登录用户的权限信息接口,获取登录用户的权限信息,包括
- 用户基本信息 user
- 用户角色集合 roles
- 用户权限标识集合 permissions
- 用户树状菜单集合 menus
将计算后的上述权限信息,写入Redis缓存。同时返回给前端,生成动态菜单。- @extend_schema(tags=["管理后台-system-认证"])
- class AuthViewSet(viewsets.GenericViewSet):
- serializer_class = AuthLoginSerializer
- queryset = SystemUsers.objects.none()
- @extend_schema(summary="获取登录用户的权限信息")
- @action(methods=["get"], detail=False, url_path="get-permission-info")
- def get_permission_info(self, request, *args, **kwargs):
- """获取登录用户的权限信息"""
- user_id = request.user.id
- cache_key = f"system_users_{user_id}"
- user = SystemUsers.objects.prefetch_related("roles", "roles__menus").get(
- id=user_id
- )
- serializer = AuthPermissionInfoSerializer(user, context={"request": request})
- cache.set(cache_key, serializer.data, timeout=None)
- return CommonResponse.success(data=serializer.data)
复制代码
读取缓存
用户执行某个API接口时,会进行权限判断。后端权限判断时,会从缓存中读取当前请求用户的权限标识集合,然后对比本次请求的权限标识(如 "system:post:query")。如果包含在集合中,则返回true,否则返回false。
点击查看RBAC权限原理
删除缓存
当用户退出登录时,删除用户的缓存信息- @extend_schema(summary="登出系统")
- @action(
- methods=["post"],
- detail=False,
- url_path="logout",
- permission_classes=[AllowAny],
- )
- def logout(self, request, *args, **kwargs):
- """登出系统"""
- cache.delete(f"system_users_{request.user.id}") # 清空用户Redis
- # ...
复制代码 点击查看完整代码
您正在阅读的是《Django从入门到实战》专栏!关注不迷路~
来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作! |