簡體   English   中英

如何在Django模型對象上記憶昂貴的計算?

[英]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_pythonget_db_prep_save

事實上有人已經做到了:看到這里

對於類方法,您應該使用django.utils.functional.cached_property

由於類方法的第一個參數是selfmemoize將保持對對象的引用和函數的結果,即使在拋出它之后也是如此。 這可能會導致垃圾收集器清理過時的對象,從而導致內存泄漏。 cached_property將Daniel的建議變成了裝飾者。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM