web-dev-qa-db-ja.com

djangoで@cached_propertyを無効にする方法

現在、モデルクラスで@cached_propertyを使用しています。次の呼び出しで再入力できるように、保存時にそれを削除したいと考えています。どうすればよいですか?例:

class Amodel():
    #...model_fields....

    @cached_property
    def db_connection(self):
        #get some thing in the db and cache here


instance = Amodel.objects.get(id=1)
variable = instance.db_connection

Amodel.objects.select_for_update().filter(id=1).update(#some variable)
#invalidate instance.db_connection
#new_variable = instance.db_connection

ありがとう

30
user1711168

ドキュメンテーションとしてそれを削除してください says 。次のアクセス時に再計算されます。

class SomeClass(object):

    @cached_property
    def expensive_property(self):
         return datetime.now()

obj = SomeClass()
print obj.expensive_property
print obj.expensive_property # outputs the same value as before
del obj.expensive_property
print obj.expensive_property # outputs new value
40
isobolev

進行中の開発のために大幅に編集...特定のcached_propertyに対して複数のタグをサポートするようになりました。

同様の問題が発生しました。関連する_cached_property_オブジェクトのセットがあり、すべて同時に無効化する必要がありました。私はそれをこのように解決しました:

  1. _cached_property_を拡張してタグ値を受け入れ、デコレータクラスメソッドを含めます。

    _def __init__(self, func, *tags):
        self.func = func
        self.tags = frozenset(tags)
    
    @classmethod
    def tag(cls *tags):
        return lambda f: cls(f, *tags)
    _
  2. 他のオブジェクトでは、新しい_cached_property.tag_デコレータクラスメソッドを使用して、タグ付き_cached_property_メソッドを定義します。

    _@cached_property.tag("foo_group")
    def foo(self):
        return "foo"
    _
  3. 新しいデコレーターを使用する私のオブジェクトで、インスタンス化されたオブジェクトのクラスの_cached_property_を歩くことによって、名前付きタグを持つすべての___dict___値を無効にするメソッドを記述します。これにより、すべての_cached_property_メソッドの偶発的な呼び出しが防止されます。

    _def invalidate(self, tag):
        for key, value in self.__class__.__dict__.items():
            if isinstance(value, cached_property) and tag in value.tags:
                self.__dict__.pop(key, None)
    _

今、無効にするために、私は単にmyobject.invalidate("foo_group")を呼び出します。

5
Thomas Baden

model.refresh_from_db()が呼び出されたときにモデルのすべての_@cached_property_プロパティを無効にするDjangoモデルミックスインを作成しました。キャッシュされたプロパティをmodel.invalidate_cached_properties()

_from Django.utils.functional import cached_property


class RefreshFromDbInvalidatesCachedPropertiesMixin():

    def refresh_from_db(self, *args, **kwargs):
        self.invalidate_cached_properties()
        return super().refresh_from_db(*args, **kwargs)

    def invalidate_cached_properties(self):
        for key, value in self.__class__.__dict__.items():
            if isinstance(value, cached_property):
                self.__dict__.pop(key, None)
_

https://gitlab.com/snippets/1747035

Thomas Baden の答えに触発されました。

4
gitaarik