9

SQLAlchemy ORM クエリに変換したい Django モデル マネージャーに次の注釈があります。

annotations = {
        'review_count' : Count("cookbookreview", distinct=True), 
        'rating' : Avg("cookbookreview__rating")
    }
return self.model.objects.annotate(**annotations)

私が本質的に必要としているのは、クエリ内の各モデル オブジェクトを最初のクエリの一部として保持し、それらにアタッチすることですreview_countratingを使用できると思いcolumn_propertyますが、テンプレートでプロパティにアクセスするときにオブジェクトごとにプロパティ (高価なルックアップ) を実行したくないため、オブジェクトでこのタイプの「計算されたプロパティ」を避けたいと思います。

この問題にアプローチする正しい方法は何ですか? 前もって感謝します。

4

1 に答える 1

13

したがって、この問題を抱えている他の人にとって完全性と有用性のために、次の解決策を提示します(これは、これを解決するための最適な方法である場合とそうでない場合があります)

sq_reviews = db_session.query(CookbookReview.cookbook_id, 
    func.avg(CookbookReview.rating).label('rating'),\
    func.count('*').label('review_count')).\
    group_by(CookbookReview.cookbook_id).subquery()

object_list = db_session.query(
    Cookbook, sq_reviews.c.rating, sq_reviews.c.review_count).\
    outerjoin(sq_reviews, Cookbook.id==sq_reviews.c.cookbook_id).\
    order_by(Cookbook.name).limit(20)

ここで重要なのは、SQLAlchemy サブクエリの概念です。元の Django クエリの各アノテーションをサブクエリと考えると、概念が理解しやすくなります。また、このクエリが非常に高速であることも注目に値します。(より簡潔で魔法の) Django の対応物よりも何桁も高速です。願わくば、これがこの特定の Django/SQLAlchemy クエリ類似物に興味を持っている他の人に役立つことを願っています。

また、ORM オブジェクトの実際のアノテーションを自分で実行する必要があることにも注意してください。オブジェクト リストをテンプレートに送信する前に、次のような単純な関数を呼び出すだけで十分です。

def process(query):
    for obj, rating, review_count in query:
        obj.rating = rating
        obj.review_count = review_count
        yield obj
于 2012-12-28T04:03:32.933 に答える