2017-08-10 62 views
1

我正在調用一個啓動一個進程的函數,這個進程需要更長的時間執行,完成了許多不同的事情。該功能主要處理特定類別的實例,Item。這些項目按不同屬性分類:category1,category2category3。現在確保queryset被緩存

,存在適用某種規則,這些類別不同的​​模式:Rule許多一對多屬性:categories1categories2categories3。規則適用於Item,如果相同的規則指向不同的類別,則只應用其中的一個。其中的一個是由封裝在函數特定邏輯中定義的決定:

class Rule(models.Model): 
    warehouse = models.ForeignKey('Warehouse') 
    categories1 = models.ManyToManyField('Category1') 
    categories2 = models.ManyToManyField('Category2') 
    categories3 = models.ManyToManyField('Category3') 

    @staticmethod 
    def get_rules_that_applies(item): 
     rules = warehouse.rule_set.all() 
     if not rules.exists(): 
      return None 
     # ... determine which rule applies to the item by filtering, etc. 
     return rule 

問題在於get_rules_that_applies方法。每次我們需要得到適用於某個項目的規則,並讓我再次說,在我們正在討論的過程中涉及許多項目時,調用warehouse.rule_set.all()

由於規則在此過程中不會改變,所以我們可以緩存倉庫中的所有規則,但怎麼做?我如何確保warehouse = warehouse.rule_set.all()被緩存,並且所有按這些規則操作的篩選和QuerySet操作都不會觸及數據庫?

+0

什麼是倉庫get_rules_that_applies? –

+0

@DimaKudosh是的我應該提到它:倉庫就像所有過程發生的「主/背景」對象。應用程序中的所有內容都圍繞着一個「倉庫」實例。 – dabadaba

回答

0

我很少信息相信你正在尋求的解決方案是memoizationget_rules_that_applies方法。

有一個現成的工具,稱爲django-memoizethose是它的文檔。在使用

快速入門:

  1. pip install django-memoize
  2. 把它放在你INSTALLED_APPS

    INSTALLED_APPS = [ 
        '...', 
        'memoize', 
    ] 
    
  3. 在你model.py

    from memoize import memoize 
    
    class Rule(models.Model): 
        warehouse = models.ForeignKey('Warehouse') 
        categories1 = models.ManyToManyField('Category1') 
        categories2 = models.ManyToManyField('Category2') 
        categories3 = models.ManyToManyField('Category3') 
    
        @staticmethod 
        @memoize(timeout=something_reasonable_in_seconds) 
        def get_rules_that_applies(item): 
         rules = warehouse.rule_set.all() 
         if not rules.exists(): 
          return None 
          # ... determine which rule applies to the item by filtering, etc. 
         return rules 
    

(更新)半DIY方法:

由於我的回答,我讀了下面的帖子:https://www.peterbe.com/plog/cache_memoize-cache-decorator-for-django這是伴隨着gist如何實現自己的memoization的。


A更多DIY方法:

的Python 3.2和至多:

@functools.lru_cache裝飾其是:

裝飾包裝一個官能團與memoizing可調用,最多可以保存最近的最大呼叫。當使用相同的參數週期性地調用昂貴的或I/O綁定函數時,它可以節省時間。

如何使用它:

from functools import lru_cache 


class Rule(models.Model): 
    ... 

    @lru_cache(maxsize=a_reasonable_integer_size_of_cache) 
    def get_rules_that_applies(item): 
     rules = warehouse.rule_set.all() 
     if not rules.exists(): 
      return None 
      # ... determine which rule applies to the item by filtering, etc. 
     return rules 

maxsize:定義函數的高速緩存的大小調用存儲。它可以設置爲None來緩存每個呼叫。

的Python < 3.2

在這裏What is memoization and how can I use it in Python?存在更多的 「老派」 的做法。


如何緩存查詢集與任一上述方法:

爲什麼不限定中間函數,以形成查詢集和高速緩存,其功能結果嗎?

@lru_cache(maxsize=None) 

or 

@memoize() 
def middle_function(): 
    return warehouse.rule_set.all() 

,然後在get_rules_that_applies功能:

def get_rules_that_applies(item): 
    rules = middle_function() 
+0

我並不是真的在超時緩存之後,它可以也應該在流程執行的整個生命週期中兌現(您當倉庫實例從內存中釋放時,可以很容易地告訴它什麼時候結束)。另外,這會緩存項目的規則嗎? (因爲它正在緩存函數結果)我不能只強制高速緩存一個查詢集? – dabadaba

+0

@dabadaba我編輯瞭如何緩存一個查詢集,因爲我想象它:) 順便說一句,對於'memoize'我不知道,但'lru_cache'似乎沒有超時。 –

+0

我剛剛意識到我不能使用'django-memoize',因爲我的Django版本較舊。 – dabadaba

0

你有2個選擇:

  1. 緩存視圖
  2. cahce在模型中項目的項目

的代碼將在視圖和模型,導入相同cahce:

from django.core.cache import cache 

代碼:

if cache.get('query_result') is not None: 
    return cache.get('query_result') 
else: 
    cache.set('query_result', result, 3600) 
    #cache.set('cache_name', 'your query', 'expiry time') 
    return rule 

你的模式將是:

class Rule(models.Model): 
warehouse = models.ForeignKey('Warehouse') 
categories1 = models.ManyToManyField('Category1') 
categories2 = models.ManyToManyField('Category2') 
categories3 = models.ManyToManyField('Category3') 

@staticmethod 
def get_rules_that_applies(item): 
    rules = warehouse.rule_set.all() 
    if not rules.exists(): 
     return None 
    # ... determine which rule applies to the item by filtering, etc. 
    if cache.get('query_result') is not None: 
     return cache.get('query_result') 
    else: 
     cache.set('query_result', result, 3600) 
     #cache.set('cache_name', 'your query', 'expiry time') 
     return rule 

    return rule 

約Django的查詢,當他們進行評估?:

https://docs.djangoproject.com/en/1.11/ref/models/querysets/#when-querysets-are-evaluated

希望這有助於

+0

這將緩存適用於該項目的規則,而不是規則的源查詢集合 – dabadaba