1

例を簡単にするために、いくつかの不完全なコードを投稿します。階層構造でいくつかのメトリックを計算するために再帰関数を実行しています。

クラス カテゴリ(models.Model):

parent = models.ForeignKey('self', null=True, blank=True, related_name='children', default=1)

def compute_metrics(self, shop_object, metric_queryset=None, rating_queryset=None)
    if(metric_queryset == None):
        metric_queryset = Metric.objects.all()
    if(rating_queryset == None):
        rating_queryset = Rating.objects.filter(shop_object=shop_object)

    for child in self.children.all():
        do stuff
        child_score = child.compute_metrics(shop_object, metric_queryset, rating_queryset)

    metrics_in_cat = metric_queryset.filter(category=self) 
    for metric in metrics_in_cat
          do stuff

何が起こっているかを確認するのに十分なコードであることを願っています。ここで求めているのは、これらのクエリをそれぞれ 1 回だけ実行し、結果を渡す再帰関数です。それは現在起こっていないようで、パフォーマンスが低下しています。これが PHP/MySQL であった場合 (Django を使用した後は嫌いですが)、クエリを一度実行して渡すことができました。

Djangoのクエリセットについて私が理解していることから、それらは私の if queryset == None then queryset=stuff 部分で評価されることはありません。どうすればこれを強制できますか? のようなことをすると再評価されmetric_queryset.filter(category=self)ますか?

データの鮮度は気にしません。メトリックと評価ごとにDBから1回読み取り、後でDBに再度アクセスせずにフィルタリングしたいだけです。非常に単純な答えが必要なように感じる、イライラする問題です。ピクルス化は機能するように見えますが、Django のドキュメントではあまり説明されていません。

4

1 に答える 1

3

ここでの問題は、再帰呼び出しが完了するまでクエリセットを評価していないことだと思います。list()クエリセットの評価を強制するために使用する場合は、データベースに1回だけヒットする必要があります。metrics_in_catクエリセットフィルターを使用するのではなく、行をPythonレベルのフィルターに変更する必要があることに注意してください。

parent = models.ForeignKey('self', null=True, blank=True, related_name='children', default=1)

def compute_metrics(self, shop_object, metric_queryset=None, rating_queryset=None)
    if(metric_queryset is None):
        metric_queryset = list([Metric.objects.all())
    if(rating_queryset is None):
        rating_queryset = list(Rating.objects.filter(shop_object=shop_object))

    for child in self.children.all():
        # do stuff
        child_score = child.compute_metrics(shop_object, metric_queryset, rating_queryset)

    # metrics_in_cat = metric_queryset.filter(category=self)
    metrics_in_cat = [m for m in metric_queryset if m.category==self]
    for metric in metrics_in_cat
        # do stuff
于 2009-08-28T08:36:10.903 に答える