动态网站的问题就在于它是动态的。 也就是说每次用户访问一个页面,服务器要执行数据库查询,启动模板,执行业务逻辑以及最终生成一个你所看到的网页,这一切都是动态即时生成的。 从处理器资源的角度来看,这是比较昂贵的。python
对于大多数网络应用来讲,过载并非大问题。 由于大多数网络应用并非washingtonpost.com或Slashdot;它们一般是很小很简单,或者是中等规模的站点,只有不多的流量。 可是对于中等至大规模流量的站点来讲,尽量地解决过载问题是很是必要的。数据库
这就须要用到缓存了。apache
缓存的目的是为了不重复计算,特别是对一些比较耗时间、资源的计算。 下面的伪代码演示了如何对动态页面的结果进行缓存。django
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
为此,Django提供了一个稳定的缓存系统让你缓存动态页面的结果,这样在接下来有相同的请求就能够直接使用缓存中的数据,避免没必要要的重复计算。 另外Django还提供了不一样粒度数据的缓存,例如: 你能够缓存整个页面,也能够缓存某个部分,甚至缓存整个网站。后端
Django也和”上游”缓存工做的很好,例如Squid(http://www.squid-cache.org)和基于浏览器的缓存。 这些类型的缓存你不直接控制,可是你能够提供关于你的站点哪部分应该被缓存和怎样缓存的线索(经过HTTP头部)给它们浏览器
缓存系统须要一些少许的设定工做。 也就是说,你必须告诉它缓存的数据应该放在哪里,在数据库中,在文件系统,或直接在内存中。 这是一个重要的决定,影响您的高速缓存的性能,是的,有些类型的缓存比其它类型快。缓存
缓存设置在settings文件的 CACHE_BACKEND
中。 这里是一个CACHE_BACKEND全部可用值的解释。安全
Memcached是迄今为止可用于Django的最快,最有效的缓存类型,Memcached是彻底 基于内存的缓存框架,最初开发它是用以处理高负荷的LiveJournal.com随后由Danga Interactive公司开源。 它被用于一些站点,例如Facebook和维基百科网站,以减小数据库访问,并大幅提升站点的性能。服务器
Memcached是免费的(http://danga.com/memcached)。它做为一个守 护进程运行,并分配了特定数量的内存。 它只是提供了添加,检索和删除缓存中的任意数据的高速接口。 全部数据都直接存储在内存中,因此没有对使用的数据库或文件系统的开销。cookie
在安装了Memcached自己以后,你将须要安装Memcached Python绑定,它没有直接和Django绑定。 这两个可用版本。 选择和安装如下模块之一:
最快的可用选项是一个模块,称为cmemcache,在http://gijsbert.org/cmemcache。
若是您没法安装cmemcache, 您能够安装python - Memcached,在ftp://ftp.tummy.com/pub/python-memcached/。若是该网址已再也不有效,只要到 Memcached的网站http://www.danga.com/memcached/),并从客户端API完成Python绑定。
若要使用Memcached的Django,设置CACHE_BACKEND到memcached:/ / IP:port/,其中IP是Memcached的守护进程的IP地址,port是Memcached运行的端口。
在这个例子中,Memcached运行在本地主机 (127.0.0.1)上,端口为11211:
CACHE_BACKEND = 'memcached://127.0.0.1:11211/'
Memcached的一个极好的特性是它在多个服务器间分享缓存的能力。 这意味着您能够在多台机器上运行Memcached的守护进程,该程序会把这些机器当成一个单一缓存,而无需重复每台机器上的缓存值。 要充分利用此功能,请在CACHE_BACKEND里引入全部服务器的地址,用分号分隔。
这个例子中,缓存在运行在IP地址为172.19.26.240和172.19.26.242,端口号为11211的Memcached实例间分享:
CACHE_BACKEND = 'memcached://172.19.26.240:11211;172.19.26.242:11211/'
这个例子中,缓存在运行在172.19.26.240(端口11211),172.19.26.242(端口11212),172.19.26.244(端口11213)的Memcached实例间分享:
CACHE_BACKEND = 'memcached://172.19.26.240:11211;172.19.26.242:11212;172.19.26.244:11213/'
最后有关Memcached的一点是,基于内存的缓存有一个重大的缺点。 因为缓存的数据存储在内存中,因此若是您的服务器崩溃,数据将会消失。 显然,内存不是用来持久化数据的,所以不要把基于内存的缓存做为您惟一的存储数据缓存。 毫无疑问,在Django的缓存后端不该该用于持久化,它们原本就被设计成缓存的解决方案。但咱们仍然指出此点,这里是由于基于内存的缓存是暂时的。
为了使用数据库表做为缓存后端,首先在数据库中运行这个命令以建立缓存表:
python manage.py createcachetable [cache_table_name]
这里的[cache_table_name]是要建立的数据库表名。 (这个名字随你的便,只要它是一个有效的表名,并且不是已经在您的数据库中使用的表名。)这个命令以Django的数据库缓存系统所指望的格式建立一个表。
一旦你建立了数据库表,把你的CACHE_BACKEND设置为”db://tablename”,这里的tablename是数据库表的名字,在这个例子中,缓存表名为my_cache_table: 在这个例子中,高速缓存表的名字是my_cache_table:
CACHE_BACKEND = 'db://my_cache_table'
数据库缓存后端使用你的settings文件指定的同一数据库。 你不能为你的缓存表使用不一样的数据库后端.
若是你已经有了一个快速,良好的索引数据库服务器,那么数据库缓存的效果最明显。
要把缓存项目放在文件系统上,请为CACHE_BACKEND使用”file://“的缓存类型。例如,要把缓存数据存储在/var/tmp/django_cache上,请使用此设置:
CACHE_BACKEND = 'file:///var/tmp/django_cache'
注意例子中开头有三个斜线。 头两项是file://,第三个是第一个字符的目录路径,/var/tmp/django_cache。若是你使用的是Windows,在file://以后加上文件的驱动器号:
file://c:/foo/bar
目录路径应该是*绝对*路径,即应该以你的文件系统的根开始。 在设置的结尾放置斜线与否可有可无。
确认该设置指向的目录存在而且你的Web服务器运行的系统的用户能够读写该目录。 继续上面的例子,若是你的服务器以用户apache运行,确认/var/tmp/django_cache存在而且用户apache能够读写/var /tmp/django_cache目录。
每一个缓存值将被存储为单独的文件,其内容是Python的pickle模块以序列化(“pickled”)形式保存的缓存数据。 每一个文件的名称是缓存键,以规避开安全文件系统的使用。
若是你想利用内存缓存的速度优点,但又不能使用Memcached,能够考虑使用本地存储器缓存后端。 此缓存的多进程和线程安全。 设置 CACHE_BACKEND
为 locmem:///
来使用它,例如:
CACHE_BACKEND = 'locmem:///'
请注意,每一个进程都有本身私有的缓存实例,这意味着跨进程缓存是不可能的。 这显然也意味着本地内存缓存效率并非特别高,因此对产品环境来讲它可能不是一个好选择。 对开发来讲还不错。
最后,Django提供了一个假缓存(只是实现了缓存接口,实际上什么都不作)。
假如你有一个产品站点,在许多地方使用高度缓存,但在开发/测试环境中,你不想缓存,也不想改变代码,这就很是有用了。 要激活虚拟缓存,就像这样设置CACHE_BACKEND:
CACHE_BACKEND = 'dummy:///'
尽管Django包含对许多缓存后端的支持,在某些状况下,你仍然想使用自定义缓存后端。 要让Django使用外部缓存后端,须要使用一个Python import路径做为的CACHE_BACKEND URI的(第一个冒号前的部分),像这样:
CACHE_BACKEND = 'path.to.backend://'
若是您构建本身的后端,你能够参考标准缓存后端的实现。 源代码在Django的代码目录的django/core/cache/backends/下。
注意 若是没有一个真正使人信服的理由,好比主机不支持,你就应该坚持使用Django包含的缓存后端。 它们通过大量测试,而且易于使用。
每一个缓存后端均可能使用参数。 它们在CACHE_BACKEND设置中以查询字符串形式给出。 有效参数以下:
timeout
:用于缓存的过时时间,以秒为单位。 这个参数默认被设置为300秒(五分钟)。max_entries:对于内存,文件系统和数据库后端,高速缓存容许的最大条目数,超出这个数则旧值将被删除。 这个参数默认是300。
cull_percentage
:当达到max_entries
的时候,被删除的条目比率。 实际的比率是1/cull_percentage
,因此设置cull_frequency=2就是在达到max_entries
的时候去除一半数量的缓存。把
cull_frequency
的值设置为0
意味着当达到max_entries
时,缓存将被清空。 这将以不少缓存丢失为代价,大大提升接受访问的速度。
在这个例子中, timeout
被设成 60
CACHE_BACKEND = "memcached://127.0.0.1:11211/?timeout=60"
而在这个例子中, timeout
设为 30
而 max_entries
为 400
:
CACHE_BACKEND = "locmem:///?timeout=30&max_entries=400"
其中,非法的参数与非法的参数值都将被忽略。
一旦高速缓存设置,最简单的方法是使用缓存缓存整个网站。 您 须要添加’django.middleware.cache.UpdateCacheMiddleware’和 ‘django.middleware.cache.FetchFromCacheMiddleware’到您的MIDDLEWARE_CLASSES设置中,在这个例子中是:
MIDDLEWARE_CLASSES = ( 'django.middleware.cache.UpdateCacheMiddleware', 'django.middleware.common.CommonMiddleware', 'django.middleware.cache.FetchFromCacheMiddleware', )
注意:
不,这里并无排版错误: 修改的中间件,必须放在列表的开始位置,而fectch中间件,必须放在最后。 细节有点费解,若是您想了解完整内幕请参看下面的MIDDLEWARE_CLASSES顺序。
而后,在你的Django settings文件里加入下面所需的设置:
CACHE_MIDDLEWARE_SECONDS
:每一个页面应该被缓存的秒数。
CACHE_MIDDLEWARE_KEY_PREFIX
:若是缓存被多个使用相同Django安装的网站所共享,那么把这个值设成当前网站名,或其余能表明这个Django实例的惟一字符串,以免key发生冲突。 若是你不在乎的话能够设成空字符串。
缓存中间件缓存每一个没有GET或者POST参数的页面。 或者,若是CACHE_MIDDLEWARE_ANONYMOUS_ONLY设置为True,只有匿名请求(即不是由登陆的用户)将被缓存。 若是想取消用户相关页面(user-specific pages)的缓存,例如Djangos 的管理界面,这是一种既简单又有效的方法。 CACHE_MIDDLEWARE_ANONYMOUS_ONLY,你应该确保你已经启动AuthenticationMiddleware。
此外,缓存中间件为每一个HttpResponse自动设置了几个头部信息:
当一个新(没缓存的)版本的页面被请求时设置Last-Modified头部为当前日期/时间。
设置Expires头部为当前日期/时间加上定义的CACHE_MIDDLEWARE_SECONDS。
设置Cache-Control头部来给页面一个最长的有效期,值来自于CACHE_MIDDLEWARE_SECONDS设置。
参阅更多的中间件第17章。
若是视图设置本身的缓存到期时间(即 它有一个最大年龄在头部信息的Cache-Control
中), 那么页面将缓存直到过时,而不是CACHE_MIDDLEWARE_SECONDS。使用django.views.decorators.cache装 饰器,您能够轻松地设置视图的到期时间(使用cache_control装饰器)或禁用缓存视图(使用never_cache装饰器)。 请参阅下面的”使用其余头部信息“小节以了解装饰器的更多信息。
更加颗粒级的缓存框架使用方法是对单个视图的输出进行缓存。 django.views.decorators.cache
定义了一个自动缓存视图响应的cache_page
装饰器。 他是很容易使用的:
from django.views.decorators.cache import cache_page def my_view(request): # ... my_view = cache_page(my_view, 60 * 15)
也可使用Python2.4的装饰器语法:
@cache_page(60 * 15) def my_view(request): # ...
cache_page
只接受一个参数: 以秒计的缓存超时时间。 在前例中, “my_view()” 视图的结果将被缓存 15 分钟。 (注意: 为了提升可读性,该参数被书写为 60 * 15
。 60 * 15
将被计算为 900
,也就是说15 分钟乘以每分钟 60 秒。)
和站点缓存同样,视图缓存与 URL 无关。 若是多个 URL 指向同一视图,每一个视图将会分别缓存。 继续 my_view
范例,若是 URLconf 以下所示:
urlpatterns = ('', (r'^foo/(\d{1,2})/$', my_view), )
那么正如你所期待的那样,发送到 /foo/1/
和 /foo/23/
的请求将会分别缓存。 但一旦发出了特定的请求(如: /foo/23/ ),以后再度发出的指向该 URL 的请求将使用缓存。
前一节中的范例将视图硬编码为使用缓存,由于 cache_page
在适当的位置对 my_view
函数进行了转换。 该方法将视图与缓存系统进行了耦合,从几个方面来讲并不理想。 例如,你可能想在某个无缓存的站点中重用该视图函数,或者你可能想将该视图发布给那些不想经过缓存使用它们的人。 解决这些问题的方法是在 URLconf 中指定视图缓存,而不是紧挨着这些视图函数自己来指定。
完成这项工做很是简单: 在 URLconf 中用到这些视图函数的时候简单地包裹一个 cache_page
。如下是刚才用到过的 URLconf : 这是以前的URLconf:
urlpatterns = ('', (r'^foo/(\d{1,2})/$', my_view), )
如下是同一个 URLconf ,不过用 cache_page
包裹了 my_view
:
from django.views.decorators.cache import cache_page urlpatterns = ('', (r'^foo/(\d{1,2})/$', cache_page(my_view, 60 * 15)), )
若是采起这种方法, 不要忘记在 URLconf 中导入 cache_page
。
你一样可使用cache
标签来缓存模板片断。 在模板的顶端附近加入{% load cache %}
以通知模板存取缓存标签。
模板标签{% cache %}
在给定的时间内缓存了块的内容。 它至少须要两个参数: 缓存超时时间(以秒计)和指定缓存片断的名称。 示例:
{% load cache %} {% cache 500 sidebar %} .. sidebar .. {% endcache %}
有时你可能想缓存基于片断的动态内容的多份拷贝。 好比,你想为上一个例子的每一个用户分别缓存侧边栏。 这样只须要给{% cache %}
传递额外的参数以标识缓存片断。
{% load cache %} {% cache 500 sidebar request.user.username %} .. sidebar for logged in user .. {% endcache %}
传递不止一个参数也是可行的。 简单地把参数传给{% cache %}
。
缓存超时时间能够做为模板变量,只要它能够解析为整数值。 例如,若是模板变量my_timeout
值为600,那么如下两个例子是等价的。
{% cache 600 sidebar %} ... {% endcache %} {% cache my_timeout sidebar %} ... {% endcache %}
这个特性在避免模板重复方面很是有用。 能够把超时时间保存在变量里,而后在别的地方复用。
有些时候,对整个经解析的页面进行缓存并不会给你带来太多好处,事实上可能会过犹不及。
好比说,也许你的站点所包含的一个视图依赖几个费时的查询,每隔一段时间结果就会发生变化。 在这种状况下,使用站点级缓存或者视图级缓存策略所提供的整页缓存并非最理想的,由于你可能不会想对整个结果进行缓存(由于一些数据常常变化),但你仍 然会想对不多变化的部分进行缓存。
针对这样的状况,Django提供了简单低级的缓存API。 你能够经过这个API,以任何你须要的粒度来缓存对象。 你能够对全部可以安全进行 pickle 处理的 Python 对象进行缓存: 字符串、字典和模型对象列表等等。 (查阅 Python 文档能够了解到更多关于 pickling 的信息。)
缓存模块django.core.cache
拥有一个自动依据CACHE_BACKEND
设置建立的django.core.cache
对象。
>>> from django.core.cache import cache
基本的接口是 set(key, value, timeout_seconds)
和 get(key)
:
>>> cache.set('my_key', 'hello, world!', 30) >>> cache.get('my_key') 'hello, world!'
timeout_seconds
参数是可选的, 而且默认为前面讲过的 CACHE_BACKEND
设置中的 timeout
参数.
若是缓存中不存在该对象,那么cache.get()
会返回None
。
# Wait 30 seconds for 'my_key' to expire... >>> cache.get('my_key') None
咱们不建议在缓存中保存 None
常量,由于你将没法区分你保存的 None
变量及由返回值 None
所标识的缓存未命中。
cache.get()
接受一个 缺省
参数。 它指定了当缓存中不存在该对象时所返回的值:
>>> cache.get('my_key', 'has expired') 'has expired'
使用add()
方法来新增一个原来没有的键值。 它接受的参数和set()
同样,可是并不去尝试更新已经存在的键值。
>>> cache.set('add_key', 'Initial value') >>> cache.add('add_key', 'New value') >>> cache.get('add_key') 'Initial value'
若是想肯定add()
是否成功添加了缓存值,你应该测试返回值。 成功返回True,失败返回False。
还有个get_many()
接口。 get_many()
所返回的字典包括了你所请求的存在于缓存中且未超时的全部键值。
>>> cache.set('a', 1) >>> cache.set('b', 2) >>> cache.set('c', 3) >>> cache.get_many(['a', 'b', 'c']) {'a': 1, 'b': 2, 'c': 3}
最后,你能够用 cache.delete()
显式地删除关键字。
>>> cache.delete('a')
也可使用incr()
或者decr()
来增长或者减小已经存在的键值。 默认状况下,增长或减小的值是1。能够用参数来制定其余值。 若是尝试增减不存在的键值会抛出ValueError。
>>> cache.set('num', 1) >>> cache.incr('num') 2 >>> cache.incr('num', 10) 12 >>> cache.decr('num') 11 >>> cache.decr('num', 5) 6
注意
incr()
/decr()
方法不是原子操做。 在支持原子增减的缓存后端上(最著名的是memcached),增减操做才是原子的。 然而,若是后端并不原生支持增减操做,也能够经过取值/更新两步操做来实现。
目前为止,本章的焦点一直是对你 本身的 数据进行缓存。 但还有一种与 Web 开发相关的缓存: 上游缓存。 有一些系统甚至在请求到达站点以前就为用户进行页面缓存。
下面是上游缓存的几个例子:
你的 ISP (互联网服务商)可能会对特定的页面进行缓存,所以若是你向 http://example.com/ 请求一个页面,你的 ISP 可能无需直接访问 example.com 就能将页面发送给你。 而 example.com 的维护者们却无从得知这种缓存,ISP 位于 example.com 和你的网页浏览器之间,透明地处理全部的缓存。
你的 Django 网站可能位于某个 代理缓存 以后,例如 Squid 网页代理缓存 (http://www.squid-cache.org/),该缓存为提升性能而对页面进行缓存。 在此状况下 ,每一个请求将首先由代理服务器进行处理,而后仅在须要的状况下才被传递至你的应用程序。
你的网页浏览器也对页面进行缓存。 若是某网页送出了相应的头部,你的浏览器将在为对该网页的后续的访问请求使用本地缓存的拷贝,甚至不会再次联系该网页查看是否发生了变化。
上游缓存将会产生很是明显的效率提高,但也存在必定风险。 许多网页的内容依据身份验证以及许多其余变量的状况发生变化,缓存系统仅盲目地根据 URL 保存页面,可能会向这些页面的后续访问者暴露不正确或者敏感的数据。
举个例子,假定你在使用网页电邮系统,显然收件箱页面的内容取决于登陆的是哪一个用户。 若是 ISP 盲目地缓存了该站点,那么第一个用户经过该 ISP 登陆以后,他(或她)的用户收件箱页面将会缓存给后续的访问者。 这一点也很差玩。
幸运的是, HTTP 提供了解决该问题的方案。 已有一些 HTTP 头标用于指引上游缓存根据指定变量来区分缓存内容,并通知缓存机制不对特定页面进行缓存。 咱们将在本节后续部分将对这些头标进行阐述。
Vary
头部定义了缓存机制在构建其缓存键值时应当将哪一个请求头标考虑在内。 例如,若是网页的内容取决于用户的语言偏好,该页面被称为根据语言而不一样。
缺省状况下,Django 的缓存系统使用所请求的路径(好比:"/stories/2005/jun/23/bank_robbed/"
)来建立其缓存键。这意味着每次请求都会使用一样的缓存版本,不考虑才客户端cookie和语言配置的不一样。 除非你使用Vary
头部通知缓存机制页面输出要依据请求头里的cookie,语言等的设置而不一样。
要在 Django 完成这项工做,可以使用便利的 vary_on_headers
视图装饰器,以下所示:
from django.views.decorators.vary import vary_on_headers # Python 2.3 syntax. def my_view(request): # ... my_view = vary_on_headers(my_view, 'User-Agent') # Python 2.4+ decorator syntax. @vary_on_headers('User-Agent') def my_view(request): # ...
在这种状况下,缓存机制(如 Django 本身的缓存中间件)将会为每个单独的用户浏览器缓存一个独立的页面版本。
使用 vary_on_headers
装饰器而不是手动设置 Vary
头部(使用像 response['Vary'] = 'user-agent'
之类的代码)的好处是修饰器在(可能已经存在的) Vary 之上进行 添加
,而不是从零开始设置,且可能覆盖该处已经存在的设置。
你能够向 vary_on_headers()
传入多个头标:
@vary_on_headers('User-Agent', 'Cookie') def my_view(request): # ...
该段代码通知上游缓存对 二者 都进行不一样操做,也就是说 user-agent 和 cookie 的每种组合都应获取本身的缓存值。 举例来讲,使用 Mozilla
做为 user-agent 而 foo=bar
做为 cookie 值的请求应该和使用 Mozilla
做为 user-agent 而 foo=ham
的请求应该被视为不一样请求。
因为根据 cookie 而区分对待是很常见的状况,所以有 vary_on_cookie
装饰器。 如下两个视图是等效的:
@vary_on_cookie def my_view(request): # ... @vary_on_headers('Cookie') def my_view(request): # ...
传入 vary_on_headers
头标是大小写不敏感的; "User-Agent"
与 "user-agent"
彻底相同。
你也能够直接使用帮助函数:django.utils.cache.patch_vary_headers
。 该函数设置或增长 Vary header ,例如:
from django.utils.cache import patch_vary_headers def my_view(request): # ... response = render_to_response('template_name', context) patch_vary_headers(response, ['Cookie']) return response
patch_vary_headers
以一个 HttpResponse
实例为第一个参数,以一个大小写不敏感的头标名称列表或元组为第二个参数。
关于缓存剩下的问题是数据的隐私性以及在级联缓存中数据应该在何处储存的问题。
一般用户将会面对两种缓存: 他或她本身的浏览器缓存(私有缓存)以及他或她的提供者缓存(公共缓存)。 公共缓存由多个用户使用,而受其余某人的控制。 这就产生了你不想遇到的敏感数据的问题,好比说你的银行帐号被存储在公众缓存中。 所以,Web 应用程序须要以某种方式告诉缓存那些数据是私有的,哪些是公共的。
解决方案是标示出某个页面缓存应当是私有的。 要在 Django 中完成此项工做,可以使用 cache_control
视图修饰器: 例如:
from django.views.decorators.cache import cache_control @cache_control(private=True) def my_view(request): # ...
该修饰器负责在后台发送相应的 HTTP 头部。
还有一些其余方法能够控制缓存参数。 例如, HTTP 容许应用程序执行以下操做:
定义页面能够被缓存的最大时间。
指定某个缓存是否老是检查较新版本,仅当无更新时才传递所缓存内容。 (一些缓存即使在服务器页面发生变化的状况下仍然会传送所缓存的内容,只由于缓存拷贝没有过时。)
在 Django 中,可以使用 cache_control
视图修饰器指定这些缓存参数。 在本例中, cache_control
告诉缓存对每次访问都从新验证缓存并在最长 3600 秒内保存所缓存版本:
from django.views.decorators.cache import cache_control @cache_control(must_revalidate=True, max_age=3600) def my_view(request): # ...
在 cache_control()
中,任何合法的Cache-Control
HTTP 指令都是有效的。下面是完整列表:
public=True
private=True
no_cache=True
no_transform=True
must_revalidate=True
proxy_revalidate=True
max_age=num_seconds
s_maxage=num_seconds
缓存中间件已经使用 CACHE_MIDDLEWARE_SETTINGS
设置设定了缓存头部 max-age 。 若是你在cache_control修饰器中使用了自定义的max_age,该修饰器将会取得优先权,该头部的值将被正确地被合并。
若是你想用头部彻底禁掉缓存,django.views.decorators.cache.never_cache
装饰器能够添加确保响应不被缓存的头部信息。 例如:
from django.views.decorators.cache import never_cache @never_cache def myview(request): # ...
Django 带有一些其它中间件可帮助您优化应用程序的性能:
django.middleware.http.ConditionalGetMiddleware
为现代浏览器增长了有条件的,基于 ETag
和 Last-Modified
头标的GET响应的相关支持。
django.middleware.gzip.GZipMiddleware
为全部现代浏览器压缩响应内容,以节省带宽和传送时间。
若是使用缓存中间件,注意在MIDDLEWARE_CLASSES
设置中正确配置。 由于缓存中间件须要知道哪些头部信息由哪些缓存区来区分。 中间件老是尽量得想Vary
响应头中添加信息。
UpdateCacheMiddleware
在相应阶段运行。由于中间件是以相反顺序运行的,全部列表顶部的中间件反而last在相应阶段的最后运行。 全部,你须要确保UpdateCacheMiddleware
排在任何可能往Vary头部添加信息的中间件以前
。 下面的中间件模块就是这样的:
添加 Cookie
的 SessionMiddleware
添加 Accept-Encoding
的 GZipMiddleware
添加Accept-Language
的LocaleMiddleware
另外一方面,FetchFromCacheMiddleware
在请求阶段运行,这时中间件循序执行,因此列表顶端的项目会首先执行。 FetchFromCacheMiddleware
也须要在会修改Vary
头部的中间件以后运行,因此FetchFromCacheMiddleware
必须放在它们后面。