Django使用redis進行緩存

對於非經常更新的服務器數據,若每次都從硬盤讀取一次,會浪費服務器資源、拖慢響應速度,而且數據更新頻率較高,服務器負擔比較大。若保存到數據庫,還需要額外建立一張對應的表存儲數據。一個更好的方法是在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.set('my_key', 'hello, world!', 30)

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相關、軟件安裝請移步從今天開始種樹。。。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章