2017-09-26 147 views
3

我使用Django的per-view @cache_page修飾器,併爲每個視圖設置了不同的key_prefixDjango使用特定的key_prefix刪除緩存

我以前刪除了與緩存:

from django.core.cache import cache 
cache.clear() 

但如果我只是想刪除包含特定key_prefix的鑰匙是什麼?我明顯可以做到這一點,只需連接到數據庫並刪除原始的SQL,但我想知道是否可以用'純粹的'Django來完成?

我正在使用數據庫緩存,而不是內存緩存。

我使用Django 1.11和Python 3.6

+1

可能重複[從Django緩存中刪除所有匹配鍵](https:// stackoverflow。com/questions/25292426/remove-all-matching-keys-from-django-cache) – lapinkoira

+0

@lapinkoira,感謝您的鏈接。鏈接問題中的答案指出,它只適用於Django localmemcache。我正在使用Django的數據庫緩存。我已經更新了答案以澄清。 – Wessi

+0

您可以使用此鏈接來解決您的問題@Wessi。 https://drupal.stackexchange.com/questions/21434/how-do-i-clear-cache-using-an-sql-query –

回答

3

由於@ e4c5提到緩存用於快速的東西,你應該使用相同的redis。但由於你的問題是關於數據庫,我會回答相同的問題。

在Django中沒有現成的函數來做到這一點。但是,然後Python的最好的部分是你可以輕鬆地猴路徑添加新的功能。下面是一個測試請求我創建

def index(request): 
    cache.set("name", "tarun") 
    cache.set("name_1", "tarun") 
    cache.set("name2", "tarun") 
    cache.set("name_4", "tarun") 
    cache.set("nam", "tarun") 

    cache.clear(prefix="name") 
    nam = cache.get("nam") 
    name_4 = cache.get("name_4", default="deleted") 
    return HttpResponse("Hello, world. nam={nam}, name_4={name_4}".format(nam=nam, name_4=name_4)) 

Patched

要獲得prefix功能,你需要添加以下代碼補丁在某些地方。我用settings.py這樣

original_clear = None 


def patch_clear(): 
    from django.db import connections, router 
    from django.core.cache.backends.db import DatabaseCache 

    def __clear(self, prefix=None, version=None): 
     db = router.db_for_write(self.cache_model_class) 
     connection = connections[db] 
     table = connection.ops.quote_name(self._table) 
     with connection.cursor() as cursor: 
      if prefix is None: 
       cursor.execute('DELETE FROM %s ' % table) 
      else: 
       prefix = self.make_key(prefix, version) 
       cursor.execute("DELETE FROM %s where cache_key like '%s%%'" % (table, prefix)) 

    global original_clear 
    original_clear = DatabaseCache.clear 
    DatabaseCache.clear = __clear 

patch_clear() 
+0

事實證明,Django實際上並不是緩存密鑰的前綴。具有添加前綴的cache_key看起來像這樣':1:views.decorators.cache.cache_page.prefixname.GET.eb9a021b08e0b96a809a931c0538e9c2.d41d8cd98f00b204e9800998ecf8427e.da-dk.Europe/Copenhagen' 我試着將你的代碼改爲f「DELETE FROM {table}其中cache_key像'%{prefix}%'「,但執行的查詢看起來像這樣'b'DELETE FROM'cache_table'其中cache_key如'%:1:prefixname%'''' 您是否有任何關於如何獲取擺脫前綴前面的':1:'? – Wessi

+1

從我的代碼中刪除'prefix = self.make_key(前綴,版本)',應該避免使用':1' –

2

TLDR; cache.deletecache.delete_many是您的可用選項。

長的答案。 @cache_page已超額定。當您使用這個裝飾器時,您經常會發現緩存總是包含比您預期更多的緩存條目。你最終想要刪除一大堆緩存條目。這似乎正是發生在這裏的事情。

我正在使用數據庫緩存而不是內存緩存。

使用緩存的一個主要思想是減少服務器上的負載,另一個是減少昂貴的計算或db查詢。但實際上,很多網頁沒有昂貴的計算。通過仔細選擇索引,可以優化大多數緩慢的查詢。

如果數據庫本身就是那個緩存,那麼就不會減少數據庫的負載。如果你需要爲不同的用戶顯示不同的內容呢?這變得非常複雜。

如果我只想刪除包含特定 key_prefix的密鑰,該怎麼辦?

考慮使用redis。這是django中最好的緩存後端之一(作爲第三方模塊)。能夠在單個命令中刪除多個密鑰是redis的許多有用功能之一。