對于非經常更新的伺服器資料,若每次都從硬碟讀取一次,會浪費伺服器資源、拖慢響應速度,而且資料更新頻率較高,伺服器負擔比較大。若儲存到資料庫,還需要額外建立一張對應的表存儲資料。一個更好的方法是在Django中使用Redis進行緩存。
緩存配置
首先安裝django-redis:
pip install django-redis
在setting檔案中設定CACHES:
CACHES = {
'default':{
'BACKEND': 'django_redis.cache.RedisCache',
'LOCATION':"redis://you_host:you_port/1",
'TIMEOUT': 200, # NONE 永不逾時
'OPTIONS':{
"PASSWORD":"you_passwd",#密碼,沒有可不設定
'CLIENT_CLASS': 'django_redis.client.DefaultClient', #redis-py 用戶端
'PICKLE_VERSION': -1, # 插件使用PICKLE進行序列化,-1表示最新版本
'CONNECTION_POOL_KWARGS': {"max_connections": 100}, # 連接配接池最大連接配接數
'SOCKET_CONNECT_TIMEOUT': 5, # 連接配接逾時
'SOCKET_TIMEOUT': 5, # 讀寫逾時
}
#"KEY_PREFIX ":"test",#字首
}
}
配置好後運作程式,進行測試:
引入庫
>>>from django.core.cache import cache
>>>cache.set("test","abscd",30)
True
同時檢視redis-cli用戶端是否寫入:
已經寫入redis,說明配置沒問題。
緩存
1.視圖緩存
緩存架構通用的方法就是緩存視圖函數,在需要進行緩存的視圖函數檔案中引入django.views.decorators.cache定義的裝飾器cache_page,它可以自動緩存視圖:
from django.views.decorators.cache import cache_page
@cache_page(60 * 15)
def my_view(request):
...
在上面的例子裡,cache_page 使用了一個參數:緩存過期時間,以秒為機關。my_view() 視圖的結果将緩存15分鐘。(注意,用 60 * 15 這樣的方式編寫,目的是友善閱讀, 也就是15分鐘),檢視一下cache_page函數的定義:
def cache_page(timeout, *, cache=None, key_prefix=None):
"""
timeout:為上面設定的逾時時間;
cache:可以指定使用哪個緩存;
key_prefix:緩存鍵值的字首,如果setting裡設定了KEY_PREFIX,它的鍵值将與KEY_PREFIX連接配接起來redis裡緩存
可以這樣使用,指定逾時時間、指定使用哪個緩存、指定鍵名字首
@cache_page(60 * 15, cache="special_cache",key_prefix="site1")
def my_view(request):
...
2.在 URLconf 中指定視圖緩存
視圖緩存還可以在url上進行。打開urls.py檔案,引入相應的庫,将需要緩存的url視圖用cache_page包裹:
from django.views.decorators.cache import cache_page
urlpatterns = [
path('foo/<int:code>/', cache_page(60 * 15)(my_view)),#緩存将保留15分鐘
]
這樣如果url (比如 /foo/23/ )已經被請求,那麼随後的請求都将使用緩存,每個url都将被單獨緩存。
3.在模闆中進行緩存
在模闆檔案中使用緩存需要在頂部先引入 {% load cache %} ,然後就可以使用 {% cache %} 标簽進行緩存操作,使用緩存标簽至少需要提供兩個參數,一個是逾時時間、一個是鍵名,如:
{% load cache %}
{% cache 500 sidebar %}#500為緩存時間,sidebar為緩存片段名稱
.. sidebar ..
{% endcache %}
如果想為每個登入使用者單獨緩存的話,可以這樣:
{% load cache %}
{% cache 500 sidebar request.user.username %} #增加了使用者這個參數,通常網站緩存還是得以使用者為基準
.. sidebar for logged in user ..
{% endcache %}
注意:這裡的緩存失效時間500可以為一個模闆變量 ,{% cache my_var sidebar %} 可以從後端傳遞過來。
底層API
剛才介紹的都是基于頁面的緩存,有時候我們并不想把頁面所有内容都緩存,有些可變内容也不适合緩存,對于這些情況django提供了一些緩存api用于更細粒度的緩存,在django文檔中所說,可以被pickle的python對象都可以緩存,這就包括:模型對象的字元串、字典、清單,大部分python對象都可以被pickle。
1.通路緩存
django.core.cache.caches
對caches的操作基本與對字典操作一樣。
>>from django.core.cache import caches
>>cache1 = caches['myalias']
>>cache2 = caches['myalias']
cache1 is cache2
True
但是當我們通路一個不存在的鍵的時候,将會抛出InvalidCacheBackendError 錯誤。這時我們可以使用:
from django.core.cache import cache
2.基本用法
cache.set(key, value, timeout=DEFAULT_TIMEOUT, version=None)
cache.get(key, default=None, version=None)
>>> cache.get('my_key')
'hello, world!'
key 是一個字元串,value 可以pickle 的Python 對象。
timeout 參數是可選的,預設為 CACHES 中相應後端的 timeout 參數。timeout 設定為 None 時将永久緩存,timeout 為0将不緩存值。
如果對象不在緩存中,cache.get() 将傳回 None。
建議不要在緩存中存儲為 None 的值,因為你不能分辨是你存儲的 None 值還是因為緩存命中傳回的 None 值。
cache.add(key, value, timeout=DEFAULT_TIMEOUT, version=None)
在鍵不存在的時候,使用 add() 方法可以添加鍵。它與 set() 帶有相同的參數,但如果指定的鍵已經存在,将不會嘗試更新緩存。
>>> cache.set('add_key', 'Initial value')
>>> cache.add('add_key', 'New value')
>>> cache.get('add_key')
'Initial value'
#cache.get("add_key"," new_value"),get方法還可以像字典一樣沒有得到值的話傳回一個預設值“new_value”
cache.get_or_set(key, default, timeout=DEFAULT_TIMEOUT, version=None)
如果你想得到鍵值或者如果鍵不在緩存中時設定一個值,可以使用 get_or_set() 方法。
>>> cache.get('my_new_key') # returns None
>>> cache.get_or_set('my_new_key', 'my new value', 100)
'my new value'
cache.get_many(keys, version=None)
cache.set_many(dict, timeout)
看示例:
>>> 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.set_many({'a': 1, 'b': 2, 'c': 3})#字典作為參數
>>> cache.get_many(['a', 'b', 'c'])
{'a': 1, 'b': 2, 'c': 3}
cache.delete(key, version=None)
cache.delete_many(keys, version=None)
>>> cache.delete('a') #删除一個鍵
>>>> cache.delete_many(['a', 'b', 'c'])#一次性删除多個
cache.incr(key, delta=1, version=None)
cache.decr(key, delta=1, version=None)
使用 incr() 或 decr() 方法來遞增或遞減一個已經存在的鍵的值,遞增或遞減一個不存在的緩存鍵,将會引發 ValueError 錯誤。
>>> cache.set('num', 1)
>>> cache.incr('num')
2
>>> cache.incr('num', 10)
12
>>> cache.decr('num')
11
>>> cache.decr('num', 5)
6
cache.touch(key, timeout=DEFAULT_TIMEOUT, version=None)
cache.touch() 為鍵設定一個新的過期時間。比如,更新一個鍵,過期時間為10秒鐘
>>> cache.touch('a', 10)
True
使用 Vary 頭
預設情況下我們的對 (http://www.happyhong.cn/)這個連結的緩存對于所有通路者都是一樣的,不能針對不同使用者代理進行差別緩存,如果想使用基于cookies、user-agent的不同進行緩存,就需要使用django提供的 django.views.decorators.vary.vary_on_headers() 視圖裝飾器,像這樣:
from django.views.decorators.vary import vary_on_headers
@vary_on_headers('User-Agent')
def my_view(request):
...
Django 自帶的緩存中間件将為每一個使用者代理即user-agent緩存一個獨立的頁面版本,傳遞給 vary_on_headers 的頭是不區分大小寫的;“User-Agent” 和 “user-agent” 是一樣的。
可以傳遞多個頭參數給 vary_on_headers():
@vary_on_headers('User-Agent', 'Cookie')
def my_view(request):
...
這就意味着要根據每個使用者代理和 cookie 的組合來擷取它自己的緩存值。
使用其它頭控制緩存
from django.views.decorators.cache import cache_control
@cache_control(private=True)
def my_view(request):
關于cache_control後續再更新吧,更多爬蟲、django相關、軟體安裝請移步從今天開始種樹。。。