UserProfileオブジェクトにJSONオブジェクトを含む複数のTextField列があります。また、JSONをPythonデータ構造にシリアライズおよびデシリアライズするためのロジックをカプセル化する各列のsetter/getterプロパティを定義しました。Djangoモデルオブジェクトの高価な計算をどのようにメモしますか?
このデータの性質上、単一のリクエスト内でビューロジックとテンプレートロジックによって何度もアクセスされることが保証されています。デシリアライゼーションコストを節約するために、私は読み込み時にpythonデータ構造をメモし、プロパティへの直接書き込みで無効にしたり、モデルオブジェクトからの信号を保存したりしたいと思います。
どこにメモを保存しますか?特定のUserProfileがクエリによってどのようにインスタンス化されているかの背後にある魔法を理解していないので、インスタンス変数を使用することについては心配です。 __init__
を安全に使用していますか、またはそれぞれの読み取り時にhasattr()
経由でメモ属性の有無を確認する必要がありますか?ここで
は私の現在の実装の例です:
def get_expensive_operation(self):
if not hasattr(self, '_expensive_operation'):
self._expensive_operation = self.expensive_operation()
return self._expensive_operation
次にあなたがデータにアクセスするためのget_expensive_operation
メソッドを使用します。一般的に
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.utils.functional.cached_property'を使用することをお勧めします。クラスメソッドの最初の引数は 'self'なので、memoizeはそれを投げ捨ててもオブジェクトと関数の結果への参照を保持します。ガベージコレクタが失効したオブジェクトをクリーンアップしないようにすることで、メモリリークを引き起こす可能性があります。 'cached_property'はダニエルの提案をデコレータに変換します。 – Arion
アリオン、これはまさに私が探していたものです:-) – pstadler