2010-12-03 13 views
2

私は単純なキャッシングトリックが実際に役に立つかどうかを判断しようとしています。私はDjangoクエリーセットが効率を改善するために怠惰だと知っていますが、データが呼び出された後にクエリの結果を保存するかどうかは疑問です。例えばdjangoクエリは、呼び出し後に結果を保存しますか?

、私は2つのモデルがある場合:


class Klass1(models.Model): 
    k2 = models.ForeignKey('Klass2') 

class Klass2(models.Model): 
    # Model Code ... 
    @property 
    def klasses(self): 
     self.klasses = Klass1.objects.filter(k2=self) 
     return self.klasses 

をそして、私はどこかklass_2_instance.klasses[:]を呼び出して、データベースにアクセスし、クエリを返しています。 klass_2_instance.klassesをもう一度呼び出すと、データベースに2回目のアクセスが行われるのだろうか、またはdjangoクエリが最初の呼び出しの結果を保存するかどうかは疑問です。

+1

'class 'ではなく' klass'が恐ろしいと言われましたか? 'cls'は、' class'がエラーを引き起こす文脈で名前が使われるなら、IMOに行く方法です。 – ThiefMaster

+0

心配する必要はありません。ここではklassを任意の名前として使用しました。これは私が使用している実際のモデルではなく、単なるコード例です。 – Arion

答えて

1

Djangoはキャッシュしません。

Klass1.objects.filter(k2 = self)の代わりに、self.klass1_set.all()を実行するだけです。 Djangoは1-nリレーションの多くの側で常にセットを作成するためです。

この種類のキャッシュは、すべてのフィルタ、除外およびorder_byが使用されているので覚えておく必要があります。うまく設計されたハッシュを使って行うことはできますが、少なくともキャッシュを無効にするパラメータが必要です。

あなたが任意のキャッシュを希望の場合は、あなたができる:すべての関連オブジェクトでするときにループを何回も

 
class Klass2(models.Model): 
    def __init__(self, *args, **kwargs): 
    self._klass1_cache = None 
    super(Klass2, self).__init__(*args, **kwargs) 

    def klasses(self): 
    if self._klass1_cache is None: 
     # Here you can't remove list(..) because it is forcing query execution exactly once. 
     self._klass1_cache = list(self.klass1_set.all()) 
    return self._klass1_cache 

これは非常に便利です。私にとっては、複数回ループする必要があるときにテンプレートでよく起こります。

1

このクエリはDjangoによってキャッシュされません。

転送 FK関係は - すなわちKlassオブジェクトklass与え、klass.k2やって - は、最初のルックアップ後にキャッシュされです。しかし、あなたがここでやっているリバースは、実際には通常klass2.klass_set.all()と綴られています - はキャッシュされていません。です。

あなたは簡単にそれをmemoizeことができます。

@property 
def klasses(self): 
    if not hasattr(self, '_klasses'): 
     self._klasses = self.klass_set.all() 
    return self._klasses 

(。あなたは、属性とメソッドklassesをオーバーライドしているとして、既存のコードが動作しないことに注意してください)

+0

興味深いことに、私はプロパティデコレータを使用しているので、実際に動作します。 Pythonは、データを変数 'klasses'に入れて、装飾されたメソッドへの参照を新しい値への参照に置き換えていると仮定します。しかし、あなたが言ったように、それはこの状況で実際にデータをキャッシュしません。 – Arion

1

はジョニー・キャッシュを使用してみてくださいクエリーセットの透過的なキャッシュが必要な場合

関連する問題