对于一个给定的url,尝试从缓存中找到对应的url网址,检查页面是否存在缓存中,如果存在,直接将缓存中的页面返回,如果缓存中没有,一系列操作(比如数据库查询)后,将内容页面保存到缓存系统中以供下次使用,并将生成的页面返回给前端。
缓存系统需要少量的配置才能使用,你必须告诉系统你的缓存数据存放在哪里-数据库还是文件系统亦或是直接存在缓存中-这是一个重要的决定,直接影响到你的缓存性能;当然,一些缓存类型本来就是比其他的快,这我们无法回避。
在项目的setting.py里面可以通过CACHES配置缓存,django中可用的缓存系统有Memcached、数据库、文件、本地内存,下面一一讲解。
Memcached作为守护进程运行,并分配了指定数量的RAM。 它所做的就是提供一个快速接口来添加,检索和删除缓存中的数据。 所有数据都直接存储在内存中,因此不会产生数据库或文件系统使用的开销。
在安装Memcached之后,您需要安装Memcached绑定。 有几个Python Memcached绑定可用; 最常见的两个是python-memcached和pylibmc。
在Django中使用Memcached:
将BACKEND设置为django.core.cache.backends.memcached.MemcachedCache或django.core.cache.backends.memcached.PyLibMCCache(具体取决于您选择的memcached绑定)
将LOCATION设置为ip:port values,其中ip是Memcached守护程序的IP地址,port是运行Memcached的端口,或者是unix:路径值,其中path是到达Memcached Unix套接字文件的路径。
在本例中,Memcached使用python-memcached绑定在本地主机(127.0.0.1)端口11211上运行:
CACHES = {
'default': {
'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache',
'LOCATION': '127.0.0.1:11211',
}
}
在本例中,Memcached通过使用python-memcached绑定的本地Unix套接字文件/tmp/memcached.sock可用:
CACHES = {
'default': {
'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache',
'LOCATION': 'unix:/tmp/memcached.sock',
}
}
Memcached的一个优秀功能是它能够在多个服务器上共享缓存。 这意味着您可以在多台机器上运行Memcached守护进程,并且程序会将这组机器视为单个缓存,而无需在每台机器上重复缓存值。 要利用此功能,请将LOCATION中的所有服务器地址包含在分号或以逗号分隔的字符串中,或作为列表。
在此示例中,高速缓存通过在IP地址172.19.26.240和172.19.26.242上运行的Memcached实例共享,这两个实例都位于端口11211上:
CACHES = {
'default': {
'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache',
'LOCATION': [
'172.19.26.240:11211',
'172.19.26.242:11211',
]
}
}
在以下示例中,缓存是通过运行在IP地址172.19.26.240(端口11211),172.19.26.242(端口11212)和172.19.26.244(端口11213)上的Memcached实例共享的:
CACHES = {
'default': {
'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache',
'LOCATION': [
'172.19.26.240:11211',
'172.19.26.242:11212',
'172.19.26.244:11213',
]
}
}
关于Memcached的最后一点是基于内存的缓存有一个缺点:因为缓存的数据存储在内存中,所以如果服务器崩溃,数据将会丢失。 很明显,内存不适用于永久数据存储,因此不要将基于内存的缓存作为唯一的数据存储。 毫无疑问,没有一个Django缓存后端应该用于永久存储 - 它们都是为了缓存而不是存储的解决方案 - 但是我们在这里指出了这一点,因为基于内存的缓存特别是暂时的。
CACHES = {
'default': {
'BACKEND': 'django.core.cache.backends.db.DatabaseCache',
'LOCATION': 'my_cache_table',
}
}
在上面操作前,我们还没建好缓存表,所以首先我们应该创建好缓存表,使用如下命令,注意cache_table_name不要和数据库中已经存在的表名冲突:
python manage.py createcachetable [cache_table_name] #这里cache_table_name即为上面的my_cache_table
这将在您的数据库中创建一个表格,该表格采用Django的数据库缓存系统所需的适当格式。 该表的名称取自LOCATION。
要打印将要运行的SQL,而不是运行它,请使用createcachetable --dry-run选项。
基于文件的后端将每个缓存值序列化并存储为单独的文件。 要使用此后端将BACKEND设置为“django.core.cache.backends.filebased.FileBasedCache”和LOCATION到合适的目录。 例如,要将缓存的数据存储在/ var / tmp / django_cache中,请使用以下设置:
CACHES = {
'default': {
'BACKEND': 'django.core.cache.backends.filebased.FileBasedCache',
'LOCATION': '/var/tmp/django_cache',
#'LOCATION': 'c:/foo/bar',#windows下的示例
}
}
注意:目录路径应该是绝对的 - 也就是说,它应该从文件系统的根目录开始。 在设置结束时是否放置斜线并不重要。必须保证服务器对你列出的路径具有读写权限。
如果你想具有内存缓存的优点但有没有能力运行Memcached的时候,你可以考虑本地内存缓存,这个缓存是多进程和线程安全的,后端设置为django.core.cache.backends.lovMemCache
CACHES = {
'default': {
'BACKEND': 'django.core.cache.backends.locmem.LocMemCache',
'LOCATION': 'unique-snowflake',
}
}
缓存LOCATION用来区分每个内存存储,如果你只有一个本地内存缓存,你可以忽略这个设置;但如果你有多个的时候,你需要至少给他们中一个赋予名字以区分他们。缓存使用最近最少使用(LRU)剔除策略。注意每个进程都有它们自己的私有缓存实例,所以跨进陈缓存是不可能的,因此,本地内存缓存不是特别有效率的,建议你只是在内部开发测时使用,不建议在生产环境中使用。
这在实际应用中时非常有用的,假如你有一个产品用发布的时候非常需要用到缓存,但在开发和测试的时候你并不想使用缓存,同时你也不想等到产品发布的时候特别的去修改缓存相关的代码,那么你可以是用虚拟缓存,要启用虚拟缓存,你只需按下面的例子去配置你的后端。
CACHES = {
'default': {
'BACKEND': 'django.core.cache.backends.dummy.DummyCache',
}
}
虽然Django支持大量缓存后端,但有时您可能需要使用自定义的缓存后端。 要在Django中使用外部缓存后端,请使用Python导入路径作为CACHES设置的BACKEND,如下所示:
CACHES = {
'default': {
'BACKEND': 'path.to.backend',
}
}
每个缓存后端可以被赋予额外的参数来控制缓存行为。这些参数作为CACHES设置中的其他键提供。有效参数如下:
TIMEOUT:用于缓存的默认超时时间(以秒为单位)。该参数默认为300秒(5分钟)。您可以将TIMEOUT设置为无,以便默认情况下缓存密钥永不过期。值为0将导致密钥立即过期(实际上“不缓存”)。
OPTIONS:应该传递给缓存后端的任何选项。有效选项的列表将随每个后端而变化,而由第三方库支持的缓存后端将直接将其选项传递到基础缓存库。
实现自己的剔除策略(即,locmem,文件系统和数据库后端)的高速缓存后端将遵循以下选项:
MAX_ENTRIES:删除旧值之前缓存中允许的最大条目数。这个参数默认为300。
CULL_FREQUENCY:达到MAX_ENTRIES时被剔除的条目的比例。实际比例为1 / CULL_FREQUENCY,因此在达到 MAX_ENTRIES时将CULL_FREQUENCY设置为2以剔除一半条目。这个参数应该是一个整数,默认为3。
对于CULL_FREQUENCY,值为0表示在达到MAX_ENTRIES时将转储整个缓存。在某些后端(特别是数据库),这会以更多的缓存未命中为代价来快速剔除。
Memcached后端将OPTIONS的内容作为关键字参数传递给客户端构造函数,允许更高级地控制客户端行为。例如用法,见下文。
KEY_PREFIX:一个字符串,将自动包含在Django服务器使用的所有缓存键中(默认预置)。
CACHES = {
'default': {
'BACKEND': 'django.core.cache.backends.filebased.FileBasedCache',
'LOCATION': '/var/tmp/django_cache',
'TIMEOUT': 60,
'OPTIONS': {
'MAX_ENTRIES': 1000
}
}
}
以下是一个基于python-memcached的后端对象大小限制为2MB的示例配置:
CACHES = {
'default': {
'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache',
'LOCATION': '127.0.0.1:11211',
'OPTIONS': {
'server_max_value_length': 1024 * 1024 * 2,
}
}
}
除了选择和设置好前面的缓存系统,还要做些其他额外的配置才行。
缓存设置完成后,使用缓存的最简单方法是缓存整个网站。 您需要将'django.middleware.cache.UpdateCacheMiddleware'和'django.middleware.cache.FetchFromCacheMiddleware'添加到setting.py文件中的MIDDLEWARE项设置中,如下例所示(设置中间件):
MIDDLEWARE = [
'django.middleware.cache.UpdateCacheMiddleware',
'django.middleware.common.CommonMiddleware'
........
'django.middleware.cache.FetchFromCacheMiddleware',
]
注意:UpdateCache中间件一定要放在第一位,Fetch中间件必须放最后(因为中间件的顺序决定着运行的顺序)
然后,将以下必需设置添加到您的Django设置文件中:
CACHE_MIDDLEWARE_ALIAS ------------------用于存储的高速缓存别名。
CACHE_MIDDLEWARE_SECONDS -------------每个页面应该被缓存的秒数,默认600。
CACHE_MIDDLEWARE_KEY_PREFIX ----------如果使用相同的Django安装跨多个站点共享缓存,请将其设置为站 点 名称或此Django实例唯一的其他字符串,以防止发生重大冲突。 如果你不在乎,请使用空字符串。如下例子:
CACHE_MIDDLEWARE_ALIAS = 'default' #用来存储的缓存别名
CACHE_MIDDLEWARE_SECONDS = 0 #所有页面默认缓存时间,默认600
CACHE_MIDDLEWARE_KEY_PREFIX ='www.demo.com' #关键的前缀,当多个站点使用同一个配置的时候,这个可以设置可以避免发生冲突,一般设置为网站域名
CACHE_MIDDLEWARE_ANONYMOUS_ONLY = False #那么只有匿名的请求会被缓存,这是一个禁用缓存非匿名用户页面的最简单的做法,注意确保已经启用了Django用户认证中间件
使用缓存框架的更细化的方式是缓存单个视图的输出。 django.views.decorators.cache定义了一个cache_page修饰器,它可以自动缓存视图的响应。 它很容易使用(请注意,为了便于阅读,我们将其写为60 * 15, 即15分钟。还要记得要先导入cache_page):
from django.views.decorators.cache import cache_page
@cache_page(60 * 15)
def my_view(request):
...
cache_page(timeout, [cache=cache name], [key_prefix=key prefix])
urlpatterns = [
path('foo//', my_view),
]
那么请求/ foo / 1 /和/ foo / 23 /将分开缓存,如您所料。 但是一旦请求了特定的URL(例如/ foo / 23 /),对该URL的后续请求将使用缓存。
@cache_page(60 * 15, cache="special_cache")
def my_view(request):
...
也可以在每个视图的基础上覆盖缓存前缀。 cache_page采用可选的关键字参数key_prefix,其工作方式与中间件的CACHE_MIDDLEWARE_KEY_PREFIX设置相同。 它可以像这样使用:
@cache_page(60 * 15, key_prefix="site1")
def my_view(request):
...
from django.views.decorators.cache import cache_page
urlpatterns = [
path('foo//', cache_page(60 * 15)(my_view)),
]
{% load cache %}
{% cache 500 sidebar %}
.. sidebar ..
{% endcache %}
有时您可能想要缓存片段的多个副本,具体取决于片段中出现的一些动态数据。 例如,您可能需要为您的网站的每个用户使用上一个示例中使用的侧栏的单独缓存副本。 通过向{%cache%}模板标签传递一个或多个可能带有或不带过滤器的变量的附加参数来唯一标识缓存片段:
{% load cache %}
{% cache 500 sidebar request.user.username %}
.. sidebar for logged in user ..
{% endcache %}
>>> from django.core.cache import caches
>>> cache1 = caches['myalias']
>>> cache2 = caches['myalias']
>>> cache1 is cache2
True
基本用法:
>>> cache.set('my_key', 'hello, world!', 30)
>>> cache.get('my_key')
'hello, world!'
键应该是一个str,并且值可以是任何可Python对象。
>>> # Wait 30 seconds for 'my_key' to expire...
>>> cache.get('my_key')
None
只有在键不存在的情况下才能添加键,请使用add()方法。 它采用与set()相同的参数,但如果指定的键已经存在,它不会尝试更新缓存:
>>> cache.set('add_key', 'Initial value')
>>> cache.add('add_key', 'New value')
>>> cache.get('add_key')
'Initial value'
还有一个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}
您可以使用delete()显式删除键。 这是清除特定对象缓存的简单方法:
>>> cache.delete('a')
from django.views.decorators.cache import cache_control
@cache_control(private=True)
def my_view(request):
...
这个装饰器负责在幕后发送适当的HTTP头。
from django.views.decorators.cache import patch_cache_control
from django.views.decorators.vary import vary_on_cookie
@vary_on_cookie
def list_blog_entries_view(request):
if request.user.is_anonymous:
response = render_only_public_entries()
patch_cache_control(response, public=True)
else:
response = render_private_and_public_entries(request.user)
patch_cache_control(response, private=True)
return response
您也可以用其他方式控制下游缓存(有关HTTP缓存的详细信息,请参阅RFC 7234)。 例如,即使您不使用Django的服务器端缓存框架,仍然可以通过max-age指令告诉客户端缓存视图一段时间:
from django.views.decorators.cache import cache_control
@cache_control(max_age=3600)
def my_view(request):
下面
列举cache_control接收到额参数: