[英]How do I memoize expensive calculations on Django model objects?
我的UserProfile對象上有幾個包含JSON對象的TextField列。 我還為每個列定義了一個setter / getter屬性,它封裝了將JSON序列化和反序列化為python數據結構的邏輯。
此數據的性質可確保在單個請求中通過視圖和模板邏輯多次訪問它。 為了節省反序列化成本,我想在讀取時記住python數據結構,在直接寫入屬性時無效或從模型對象保存信號。
在哪里/如何存儲備忘錄? 我對使用實例變量感到緊張,因為我不理解查詢實例化任何特定UserProfile背后的魔力。 __init__
是否可以安全使用,或者我是否需要在每次讀取時通過hasattr()
檢查memo屬性是否存在?
這是我當前實現的一個示例:
class UserProfile(Model):
text_json = models.TextField(default=text_defaults)
@property
def text(self):
if not hasattr(self, "text_memo"):
self.text_memo = None
self.text_memo = self.text_memo or simplejson.loads(self.text_json)
return self.text_memo
@text.setter
def text(self, value=None):
self.text_memo = None
self.text_json = simplejson.dumps(value)
您可能對內置的django裝飾器django.utils.functional.memoize
。
Django使用它來緩存昂貴的操作,如url解析。
一般來說,我使用這樣的模式:
def get_expensive_operation(self):
if not hasattr(self, '_expensive_operation'):
self._expensive_operation = self.expensive_operation()
return self._expensive_operation
然后使用get_expensive_operation
方法訪問數據。
但是,在您的特定情況下,我認為您正在以一種錯誤的方式接近這一點。 首次從數據庫加載模型時需要進行反序列化,並且僅在保存時進行序列化。 然后,您每次只需將屬性作為標准Python字典進行訪問即可。 您可以通過定義自定義JSONField類型,子類化models.TextField來執行此操作,該類型將覆蓋to_python
和get_db_prep_save
。
事實上有人已經做到了:看到這里 。
對於類方法,您應該使用django.utils.functional.cached_property
。
由於類方法的第一個參數是self
, memoize
將保持對對象的引用和函數的結果,即使在拋出它之后也是如此。 這可能會導致垃圾收集器清理過時的對象,從而導致內存泄漏。 cached_property
將Daniel的建議變成了裝飾者。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.