在以下示例中,當調用數據庫昂貴的屬性(示例中爲related_spam
)時,將使用cached_attr
來獲取或設置模型實例的屬性。在這個例子中,我使用cached_spam
來保存查詢。我在設置和獲取值時會打印報表,以便我可以對其進行測試。我在一個視圖中通過將Egg
實例傳遞到視圖中並在視圖中使用{{ egg.cached_spam }}
以及Egg
模型上的其他方法來自己調用cached_spam
來測試它。當我完成並測試了Django的開發服務器中的shell輸出後,發現屬性緩存被錯過了好幾次,並且成功獲得了好幾次。這似乎不一致。使用相同的數據,當我做出很小的更改(與更改打印語句的字符串一樣小)並刷新(使用所有相同的數據)時,會發生不同數量的錯過/成功。這是怎麼發生的呢?這段代碼是不正確的還是很成問題的?Python - 緩存屬性以避免將來計算
class Egg(models.Model):
... fields
@property
def related_spam(self):
# Each time this property is called the database is queried (expected).
return Spam.objects.filter(egg=self).all() # Spam has foreign key to Egg.
@property
def cached_spam(self):
# This should call self.related_spam the first time, and then return
# cached results every time after that.
return self.cached_attr('related_spam')
def cached_attr(self, attr):
"""This method (normally attached via an abstract base class, but put
directly on the model for this example) attempts to return a cached
version of a requested attribute, and calls the actual attribute when
the cached version isn't available."""
try:
value = getattr(self, '_p_cache_{0}'.format(attr))
print('GETTING - {0}'.format(value))
except AttributeError:
value = getattr(self, attr)
print('SETTING - {0}'.format(value))
setattr(self, '_p_cache_{0}'.format(attr), value)
return value
我想到了這個煩惱,並意識到解決這個問題的另一種方法是使用`with`模板標籤爲計算結果創建一個別名。 – nedned 2011-05-11 04:16:12
@humble - thx,這實際上是一個相當有用的筆記。 – orokusaki 2011-05-12 19:44:44