[英]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_count
和rating
。 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.