caching - 即使有空的 redis 键,Django REST 框架仍然会响应缓存数据
问题描述
上下文:我在ModelViewSet
使用方法 decorator 通过 Django REST 框架 (DRF) 中的 redis API 视图进行缓存时遇到问题cache_page
。
文档参考:https ://www.django-rest-framework.org/api-guide/caching/
代码片段:https ://hastebin.com/apoqeloyav.py
示例场景
这是当前行为(使用 Swagger UI 手动测试)
将 GET 请求发送到 /products 端点 -> 这将请求我的 DRF 服务器并缓存视图
再次向 /products 端点发送 GET 请求 -> 这会将产品数据作为缓存数据响应(已在开发工具网络选项卡“从磁盘缓存提供服务”中验证)。这也意味着它没有访问我的 DRF 服务器来检索数据。
向 /products/{product_id} 端点发送 PATCH 请求 -> 这将更新详细信息然后使缓存无效(此时 Redis 缓存键为空)
再次向 /products 端点发送 GET 请求 ->这仍会将产品数据作为缓存数据响应(已验证,因为执行步骤 3 的更新数据仍然不存在)。这也意味着它没有访问我的 DRF 服务器来检索数据。
这是我的预期行为(使用 Swagger UI 手动测试)
- 将 GET 请求发送到 /products 端点 -> 这将请求我的 DRF 服务器并缓存视图
- 再次向 /products 端点发送 GET 请求 -> 这会将产品数据作为缓存数据响应(已在开发工具网络选项卡“从磁盘缓存提供服务”中验证)。这也意味着它没有访问我的 DRF 服务器来检索数据。
- 向 /products/{product_id} 端点发送 PATCH 请求 -> 这将更新详细信息然后使缓存无效(此时 Redis 缓存键为空)
- 再次向 /products 端点发送 GET 请求 ->这应该响应来自数据库的产品数据。这意味着它会访问我的 DRF 服务器以检索更新的数据。
如何获得预期的结果,以便如果 redis 缓存为空,它应该访问我的 DRF 服务器以检索最新数据并缓存后续调用,直到它再次失效?另外,我不确定这是一个问题,还是只是正常行为。
到目前为止,这是我在使 redis 中的缓存数据无效时尝试的方法,但它们都不起作用并且仍然提供缓存数据
- 将缓存过期设置为 0
- 将缓存值设置为无
- 以编程方式删除所有键
- 通过 redis-cli 删除所有密钥
- 关闭 redis-server -> 但仍然服务
from disk cache
并且没有命中我的 DRF API 端点
这是我正在使用的版本
- djangorestframework==3.11.0
- Django==3.0.8
- redis==3.5.3
- drf-yasg==1.17.1 -> 这是 Swagger UI 文档
- django-redis==5.0.0
解决方案
来自 4. 的请求甚至没有命中 redis 缓存,因为它返回了本地缓存(请注意响应代码中的“来自磁盘缓存”)。
您应该区分公共缓存(即所有用户使用的服务器缓存)和私有缓存(用户的浏览器缓存)。
我认为,在使用cache_page
装饰器时,除了缓存请求之外,它还设置“缓存控制”响应标头以允许请求的私有缓存。浏览器使用这些标头在本地缓存请求,并返回本地缓存的响应,直到max-age
过期。
为了防止这种行为,在服务器级别,您可以使用@never_cache
装饰器,它设置Cache-control
响应标头以防止本地缓存,或者使用@cache_control(public=True)
仅允许请求的公共缓存(这也相应地调整缓存控制响应标头)。
更多关于控制缓存。
推荐阅读
- python - 多个 if 条件给了我错误的答案
- spring-boot - 当我想我尝试了很多解决方案时,如何在 Kotlin 和 Gradle 项目中使用 DevTools?
- python - 为什么 tf.matmul 不能与转置张量一起使用?
- css - 如何在详细信息上方设置 Woocommerce 产品图片
- excel - 根据多个单元格值隐藏或取消隐藏工作表
- python - 无法在scrapy的解析回调中发送请求
- python - 过大的预测 MLPRegressor
- python-3.x - 如何打开已编译的 Python 文件 (.pyc)
- ios - css 媒体查询不适用于 ipad 横向模式
- syntax - 尝试定义内部函数时出现语法错误