Django注释的SQLAlchemy转换

pat*_*ckn 5 python django sqlalchemy

我想将Django模型管理器中的以下注释转换为SQLAlchemy ORM查询:

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

我本质上需要的是在查询中有每个模型对象review_count,并rating连接到它们作为初始查询的一部分。我相信我可以使用column_property,但是我想避免在对象上使用这种类型的“计算属性”,因为当我访问模板中的属性时,我不希望为每个对象完成该属性(昂贵的查找)。

解决这个问题的正确方法是什么?提前致谢。

pat*_*ckn 5

因此,出于对这个问题的完整性和实用性的考虑,我提出以下解决方案(可能是也可能不是解决此问题的最佳方法)

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)
Run Code Online (Sandbox Code Playgroud)

这里的关键是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
Run Code Online (Sandbox Code Playgroud)