简体   繁体   English

Django注释的SQLAlchemy转换

[英]SQLAlchemy conversion of Django annotate

I have the following annotation in a Django model manager I'd like to convert to a SQLAlchemy ORM query: 我想将Django模型管理器中的以下注释转换为SQLAlchemy ORM查询:

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

What I essentially need is each model object in the query to have review_count and rating attached to them as part of the initial query. 我本质上需要的是查询中的每个模型对象在初始查询中都附加有review_countrating I believe I can use column_property , but I would like to avoid this type of "calculated property" on the object, because I don't want the property (expensive lookup) being done for each object when I access the property in a template. 我相信我可以使用column_property ,但是我想避免在对象上使用这种类型的“计算属性”,因为当我访问模板中的属性时,我不希望为每个对象完成该属性(昂贵的查找)。

What is the right way to approach this problem? 解决这个问题的正确方法是什么? Thanks in advance. 提前致谢。

So, for the sake of completeness and usefulness for others with this issue I present the following solution (which may or may not be the optimal way to solve this) 因此,出于对其他人的完整性和实用性的考虑,我提出以下解决方案(可能是,也可能不是解决此问题的最佳方法)

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)

The key here is the concept of SQLAlchemy subqueries . 这里的关键是SQLAlchemy子查询的概念。 If you think of each annotation in my original Django query as a subquery, the concept is easier to understand. 如果您将我最初的Django查询中的每个注释都视为子查询,则该概念更易于理解。 It's also worth noting that this query is quite speedy - many orders of magnitude swifter than it's (more concise/magical) Django counterpart. 还值得注意的是,此查询速度非常快-比Django(更简明/神奇)的对应对象快了多个数量级。 Hopefully this helps others curious about this particular Django/SQLAlchemy query analog. 希望这可以帮助其他人对此特定的Django / SQLAlchemy查询模拟感到好奇。

Also keep in mind that you need to perform the actual annotation of the ORM objects yourself. 还要记住,您需要自己执行ORM对象的实际注释。 A simple function like this called before sending the object list to your template will suffice: 在将对象列表发送到模板之前调用一个简单的函数就足够了:

def process(query):
    for obj, rating, review_count in query:
        obj.rating = rating
        obj.review_count = review_count
        yield obj

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM