【Django】Django中的缓存

news2024/11/15 23:32:41

缓存

1 缓存的定义

  • 定义:缓存是一类可以更快的读取数据的介质统称,也指其他可以加快数据读取的存储方式,一般用来存储临时数据,常用介质的是读取速度很快的内存。

  • 意义:视图渲染有一定成本,数据库的频繁查询过高,所以对于低频变动的页面可以考虑使用缓存技术,减少实际渲染次数,用户拿到响应的时间成本会更低。

  • Django 缓存的实现方法

    # Django 官网
    # https://docs.djangoproject.com/en/5.0/topics/cache/
    # given a URL, try finding that page in the cache
    if the page is in the cache:
        return the cached page
    else:
        generate the page
        save the generated page in the cache (for next time)
        return the generated page

  • 缓存场景:

    1. 博客列表页

    2. 电商商品详情页

    场景特点:缓存的地方,数据变动频率较少。

2 缓存的配置

2.1 Mysql缓存

将缓存的数据存储在数据库中。

说明:尽管存储介质没有更换,但是当把一次负责查询的结果直接存储到表里,比如多个条件的过滤查询结果,可避免重复进行复杂的查询,提升效率。

settings.py 中添加 CACHES 配置块。

CACHES = {
    "default": {
        "BACKEND": "django.core.cache.backends.db.DatabaseCache",
        "LOCATION": "my_cache_table", # 缓存表的名称
        "TIMEOUT": 300, #缓存的保存时间,单位秒,默认值是300
        "POTIONS":{
            "MAX_ENTRIES": 300, # 缓存最大的数据条数
            "CULL_FREQUENCY": 2 # 缓存条数达到最大值时,删除 1/CULL_FREQUENCY 的缓存数据
        }
    }
}

创建缓存表。

python3 manage.py createcachetable

查看数据库。

使用 mysql 进行缓存,会将数据存储在指定的 mysql 表中。

2.2 Redis缓存

Redis是一个内存数据库,可用于缓存。

settings.py 中添加如下 CACHES 块。

CACHES = {
    "default": {
        "BACKEND": "django.core.cache.backends.redis.RedisCache",
        "LOCATION": "redis://username:password@127.0.0.1:6379", # username、password需要看redis是否启用身份认证,如未启用,这里则不需要配置。
        # "LOCATION": [
        #    "redis://127.0.0.1:6379",  # leader
        #    "redis://127.0.0.1:6378",  # read-replica 1
        #    "redis://127.0.0.1:6377",  # read-replica 2
        # ],
        # 如果有多个redis服务器时,这样配置即可
    }
}

2.3 本地内存缓存

数据缓存到服务器内存中,如果配置文件中没有指定其他缓存,那么这是默认的缓存。如果你想获得内存缓存的速度优势,但又不具备运行 Memcached 的能力,可以考虑使用本地内存缓存后端。这个缓存是每进程所有(见下文)和线程安全的。

settings.py 中添加如下 CACHES 块。

# 说明:如下仅供测试,建议将数据存储到内存数据库中,如redis
# 每个进程都会有自己的私有缓存实例,这意味着不可能进行跨进程缓存,也即本地内存缓存的内存效率不是特别高,所以对于生产环境来说,它可能不是一个好的选择。对于开发来说是不错的选择。
CACHES = {
    "default": {
        "BACKEND": "django.core.cache.backends.locmem.LocMemCache",
        "LOCATION": "unique_snowflake", 
    }
}

2.4 文件系统缓存

将缓存的数据存储到本地文件中。

settings.py 中添加如下 CACHES 块。

CACHES = {
    "default": {
        "BACKEND": "django.core.cache.backends.filebased.FileBasedCache",
        "LOCATION": "/home/euansu/tmp", # 这个是文件夹的路径
        # "LOCATION": "c:\test\cache", # windows下示例
    }
}

使用文件系统缓存,会在配置的目录下生成对应的缓存文件。

3 整体缓存策略

整体缓存这里指的是直接缓存一个视图函数全部的结果,与下部分的局部缓存形成对照。

3.1 视图函数

from django.views.decorators.cache import cache_page
​
@cache_page(30)
def my_view(request):
    ...

代码示例

from django.shortcuts import render
from django.views.decorators.cache import cache_page
from django.http import HttpResponse
# Create your views here.
from datetime import datetime
import pytz
​
@cache_page(30)
def mysql_cache(request):
    """
    MysqlCache
    :param request: 
    :return: 
    """
    target_timezone = pytz.timezone('Asia/Shanghai')
    current_time = datetime.now()
    current_time_shanghai = current_time.replace(tzinfo=pytz.utc).astimezone(target_timezone)
​
    time_string = current_time_shanghai.strftime("%Y-%m-%d %H:%M:%S")
​
    return HttpResponse(time_string)

3.2 路由函数

from django.views.decorators.cache import cache_page
​
urlpatterns = [
    path('foo/', cache_page(60)(my_view)),
]

代码示例

from django.urls import path
from django.views.decorators.cache import cache_page
from . import views
​
urlpatterns = [
    path("mysql_cache/", cache_page(60)(views.mysql_cache)),
]

4 局部缓存策略

视图函数局部耗时较多,但视图函数其他区域并不耗时。

4.1 使用场景

  • 使用场景

    # 局部耗时较多,但视图函数其他区域并不耗时
    from django.shortcuts import render
    ​
    def index(request):
        # 时间复杂度极高的渲染
        book_list = Book.objects.all() # 假设此处耗时2s
        return render(request,'idnex.html',locals())

4.2 局部缓存的使用

# 先引入cache对象
​
## 方式一:使用caches['CACHE配置key']导入具体对象
from django.core.cache import cache
cache1 = caches['default']
cache2 = caches['custom']
​
## 方式二:
from django.core.cache import cache
# 相当于直接引入 CACHES 配置项中的'default'项

4.3 局部缓存的方法

  1. cache.set(key, value, timeout),存储缓存

    key:缓存的key,字符串类型
    value:Python对象
    timeout:缓存存储时间(s),默认为CACHES中的TIMEOUT值
    返回值:None
  2. cache.get(key),获取缓存

    key:缓存的key
    返回值:为key的具体值,如果没有数据,则返回None
  3. cache.add(key, value),存储缓存,只在key不存在时生效

    返回值:True[存储成功] or False[存储失败]
  4. cache.get_or_set(key, value, timeout),如果未获取到数据,则执行set操作

    返回值:value
  5. cache.set_many(dict, timeout),批量存储缓存

    dict:key和value的字典
    timout:存储的时间(s)
    返回值:插入不成功的key的数组
  6. cache.get_many(key_list),批量获取缓存数据。

    key_list:包含key的数组
    返回值:渠道的key和value的字典
  7. cache.delete(key),删除key的缓存数据。

    返回值:None
  8. cache.delete_many(key_list),批量删除。

    返回值:None

4.4 局部缓存测试

代码示例:

# 设置cache
from django.core.cache import cache
​
cache.set("uname", "euansu", 300)
​
cache.get("uname")

数据库中出现对应cache记录。

# 修改cache
cache.set("uname", "nange", 300)
​
cache.get("uname")

# 删除cache
cache.delete("uname")
​
cache.get("uname")

查询数据库,对应的缓存消失

5 浏览器缓存策略

浏览器也具备缓存技术,对于浏览器来说,每次向服务器发出请求都是耗时的操作,如果本身浏览器内部就具备当前 url 的内容,则一定时间内可以不必给服务器发消息,从而提升网页体验,降低服务器的请求压力。

浏览器缓存原理图

5.1 浏览器缓存-强缓存

不会向服务器发送请求,直接从缓存中读取资源。

服务器和浏览器之间的请求,通过如下两个响应头进行沟通。

  1. 响应头 - Expires

    定义:缓存过期时间,用来指定资源到期的时间,是服务器端的具体的时间点
    样例:Expires:Thu, 02 Apr 2030 05:15:08 GMT
  2. 响应头 - Cache-Control

    在HTTP/1.1中,Cache-Control主要用于控制网页缓存,比如当 Cache-Control:max-age=120 代表请求创建后的120秒,缓存失败
    说明:目前服务器都会带着这两个头同时响应给浏览器,浏览器优先使用 Cache-Control

例如如下请求,浏览器中显示已缓存。

刷新页面,但浏览器中仅有一次请求。

查看请求响应,发现返回的响应中有 Cache-ControlExpires 两个响应头。

这里的 max-age=60 是通过 cache-page 实现的。

修改 cache_page 的参数,响应头中的 max-age 也发生变化。

5.2 浏览器缓存-协商缓存

图片、静态文件等这类比较费带宽且不易变化的数据,浏览器会跟服务器协商,确认当前的缓存是否可用,如果可用,服务器不需要返回数据,浏览器继续使用原来缓存的数据,如果文件不可用,则返回最新的数据。

  1. Last-Modified 响应头和 If-Modified-Since 请求头。

    说明:

    • Last-modified 为文件的最近修改时间,浏览器第一次请求静态文件时,服务器第一次请求静态文件时,服务器如果返回Last-Modified响应头,则代表该资源为需要协商的缓存。

    • 当缓存到期后,浏览器将获取到的 Last-Modified 值作为请求头 If-Modified-Since 的值,与服务器发请求协商,服务器端返回304响应码[响应体为空],代表缓存继续使用,200响应码代表缓存不可用[响应体为最新资源]。

    代码示例

    from django.http import HttpResponse
    from django.utils import timezone
    ​
    def last_modified(request):
        """
        测试last-modified请求头
        :param request:
        :return:
        """
        last_modified_time = timezone.now()
    ​
        # 检查 If-Modified-Since 头
        if request.META.get('HTTP_IF_MODIFIED_SINCE'):
            # 如果资源没有发生变化,返回 304 Not Modified
            return HttpResponse(status=304)
    ​
        # 如果资源发生了变化,设置 Last-Modified 响应头
        response = HttpResponse("Your content here")
        response['Last-Modified'] = last_modified_time.strftime('%a, %d %b %Y %H:%M:%S GMT')
        return response
  2. ETag 响应头和 If-None-Match 请求头。

    说明:

    • ETag时服务器响应请求时,返回当前资源文件的一个唯一标识(由服务器生成),只要资源有变化,ETag就会重新生成。

    • 缓存到期后,浏览器将ETag响应头的值作为If-None-Match请求头的值,给服务器发请求协商,服务器接到请求头后,比对文件标识,不一致则认为资源不可用,返回200响应码[响应体为最新资源],可用则返回304响应码。

    代码示例

    from django.http import HttpResponse
    import hashlib
    
    def etag_func(request):
        # 获取或计算资源的内容(假设这里是一个字符串)
        resource_content = "Your content here"
    
        # 计算 ETag(使用 MD5 散列作为示例,你可以根据需要选择其他方法)
        etag = hashlib.md5(resource_content.encode('utf-8')).hexdigest()
    
        # 检查 If-None-Match 头
        if request.META.get('HTTP_IF_NONE_MATCH') == etag:
            # 如果资源没有发生变化,返回 304 Not Modified
            return HttpResponse(status=304)
    
        # 如果资源发生了变化,设置 ETag 响应头
        response = HttpResponse(resource_content)
        response['ETag'] = etag
        return response

    首次访问返回200。

    再次请求,响应变为304。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1437774.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

电力负荷预测 | Matlab实现基于LSTM长短期记忆神经网络的电力负荷预测模型(结合时间序列)

文章目录 效果一览文章概述源码设计参考资料效果一览 文章概述 电力负荷预测 | Matlab实现基于LSTM长短期记忆神经网络的电力负荷预测模型(结合时间序列) 所谓预测,就是指通过对事物进行分析及研究,并运用合理的方法探索事物的发展变化规律,对其未来发展做出预先估计和判断…

UE4 C++创建摄像机摇臂和相机并且设置Transform

新建MyPawn C类 .h #include "GameFramework/SpringArmComponent.h" //SpringArm组件 #include "Camera/CameraComponent.h" //Camera组件class 工程名称_API AMyPawn : public APawn { //定义组件变量 public:UPROPERTY(VisibleAnywhere, BlueprintRead…

【数据库原理及应用】简答题归纳总结

第一章 数据库概论 1.人工管理阶段数据管理的特点: (1)数据不保存在机器中 (2)无专用的软件对数据进行管理 (3)只有程序的概念,没有文件的概念 (4)数据面向程…

2024-02-06 TCP/UDP work

1. 画出TCP三次握手和四次挥手的示意图,并且总结TCP和UDP的区别 三次握手: 4次挥手: tcp/udp区别 TCP 1. 稳定,提供面向连接的,可靠的数据传输服务 2. 传输过程中,数据无误、数据无丢失、数据无失序、…

在 Docker 中启动 ROS2 里的 rivz2 和 rqt 出现错误的解决方法

1. 出现错误: 运行 ros2 run rivz2 rivz2 ,报错如下 : No protocol specified qt.qpa.xcb: could not connect to display :1 qt.qpa.plugin: Could not load the Qt platform plugin "xcb" in "" even though it was f…

[自然语言处理|NLP] 文本分类与情感分析,数据预处理流程,包括了同义词替换和拼写纠正,以及使用NLTK库和TextBlob库进行标记化和情感分析(附代码)

[自然语言处理|NLP] 文本分类与情感分析,数据预处理流程,包括了同义词替换和拼写纠正,以及使用NLTK库和TextBlob库进行标记化和情感分析(附代码)。 自然语言处理(Natural Language Processing,简称NLP)是人工智能领域的一个重要分支,涉及了处理和理解人类语言的技术…

2024年R2移动式压力容器充装证模拟考试题库及R2移动式压力容器充装理论考试试题

题库来源:安全生产模拟考试一点通公众号小程序 2024年R2移动式压力容器充装证模拟考试题库及R2移动式压力容器充装理论考试试题是由安全生产模拟考试一点通提供,R2移动式压力容器充装证模拟考试题库是根据R2移动式压力容器充装最新版教材,R2…

centos 7.6 安装cas 对接ldap 单点登录实战

centos 7.6 安装cas 对ldap 单点登录实战 1、安装前准备工作1.1、centos 7.6 安装JDK 1.81.2、centos 7 安装tomcat 9.0.841.3、windows10 安装JDK 1.81.4、windows10 安装打包工具 maven 3.9.6 2、下载cas 5.3 并打包成war包3、部署cas到tomcat4、cas对接ldap 1、安装前准备工…

百度拟将量子实验室捐赠予北京量子院 /一汽解放与华为合作,预计2025年底量产自动驾驶产品 |魔法半周报

我有魔法✨为你劈开信息大海❗ 高效获取AIGC的热门事件🔥,更新AIGC的最新动态,生成相应的魔法简报,节省阅读时间👻 🔥资讯预览 百度捐赠量子实验室推进量子计算研究,助力人工智能发展 一汽解放…

qt学习:mplayer播放器(视频)+arm如何播放视频实战+c启动播放器

目录 作用 linux下载 arm下载 使用方法 键盘 命令 命令词有很多,举例几个 在arm上qt实战 配置ui界面 添加头文件,成员,函数 添加视频按钮点击事件 列表选项双击事件 播放按钮点击事件 暂停继续按钮点击事件 停止按钮点击事件 …

远程主机可能不符合glibc和libstdc++ VS Code服务器的先决条件

报错信息 VSCode无法连接远程服务器,终端一直提醒: [22:46:01.906] > Waiting for server log... [22:46:01.936] > Waiting for server log... [22:46:01.951] > [22:46:01.967] > Waiting for server log... [22:46:01.982] > [22:…

我在项目中使用Redis的几个场景

目录 缓存 会话存储 分布式锁 消息队列 位统计 计数器 排行榜 缓存 缓存的目的是为了提高系统响应速度、减少数据库等资源的压力,redis作为键值对形式的内存数 据库,可以提供非常快速的读取速度,使得它成为存储热点数据或频繁访问数…

iPhone 14支持NFC吗?如果支持,那么怎么启用

你准备好通过启用NFC来释放iPhone 14的全部潜力了吗?如果你曾经想知道如何在你的设备上利用NFC,那么你就来对地方了。 在本综合指南中,我们将引导你完成在iPhone 14上激活NFC的步骤,使你能够无缝连接其他设备,进行非接…

Linux------命令行参数

目录 前言 一、main函数的参数 二、命令行控制实现计算器 三、实现touch指令 前言 当我们在命令行输入 ls -al ,可以查看当前文件夹下所有文件的信息,还有其他的如rm,touch等指令,都可以帮我们完成相应的操作。 其实运行这些…

c#cad 创建-直线(五)

运行环境 vs2022 c# cad2016 调试成功 一、代码说明 这段代码是用于在AutoCAD中创建一条直线。首先获取当前活动文档和数据库的引用,然后创建一个编辑器对象用于提示用户输入。接下来,在一个事务中获取模型空间的块表记录,并定义直线的长度…

Python模拟点赞助手

背景 之前公司一直会安排各种学习任务,视频章节很多的视频,有些是技术的有些是政策相关的,如果没有按时完成学习任务会被通报。但是,这些学习内容不一定有帮助,所以大家就养成了刷课的习惯,也就是点开视频…

网络协议与攻击模拟_15FTP协议

了解FTP协议 在Windows操作系统上使用serv-U软件搭建FTP服务 分析FTP流量 一、FTP协议 1、FTP概念 FTP(文件传输协议)由两部分组成:客户端/服务端(C/S架构) 应用场景:企业内部存放公司文件、开发网站时利…

离线场景下任意文档的在线预览及原样格式翻译,不依赖其他厂商接口非侵入式一行js代码实现网站的翻译及国际化,可配置使用多种翻译语言

离线场景下任意文档的在线预览及原样格式翻译,不依赖其他厂商接口非侵入式一行js代码实现网站的翻译及国际化,可配置使用多种翻译语言。 要实现翻译需要解决以下3个主要问题: 1)from:内容本身的语言类型是什么&#xf…

Android Studio从零基础到APP上线(3)

第3章 简单控件 本章介绍App开发常见的几类简单控件的用法,主要包括:显示文字的文本视图,容纳视图的常用布局,响应点击的按钮控件,显示图片的图像视图等。然后结合本章所学的知识,演示一个实战项目“简单计算器”的设计与实现。 3.1 文本显示 本节介绍如何在文本视图Tex…

社交分享效果统计:Xinstall助您精确追踪用户行为,优化推广策略

在移动互联网时代,社交分享已成为App推广的重要手段之一。通过微信、QQ等社交工具及主流浏览器的多渠道分享邀请,可以实现裂变式的推广效果,迅速扩大App的用户群体。然而,如何精确统计社交分享带来的安装量、注册量等关键数据&…