2012-12-27 61 views
3

我有一個Django的模型管理器下面的註解,我想轉換爲SQLAlchemy的ORM查詢:SQLAlchemy的轉換註釋

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

我本質上需要的是查詢中的每個模型對象有作爲初始查詢的一部分附加到它們的review_countrating。我相信我可以使用column_property,但我想避免這種類型的「計算屬性」對象,因爲我不想爲每個對象完成屬性(昂貴的查找),當我訪問模板中的屬性。

解決此問題的正確方法是什麼?提前致謝。

+0

恕我直言,Django註釋和聚合是非常不一致的黑客。 SQLAlchemy比Django ORM更強大,基本上,您可以以可重用和參數化的方式掌握SQL的全部功能。 –

+1

謝謝,但Django ORM聚合/註釋在這裏解決的問題仍然需要在SQLAlchemy中解決。由於它的功能非常強大,我認爲這種查詢可以相對容易地完成。儘管如此,我還是無法弄清楚。 – patrickn

+0

您可以使用SqlSoup來映射任何sqlalchemy.sql.select。 –

回答

2

所以,完整性和實用性的考慮別人這個問題我提出以下解決方案(這可能會或可能不會解決這個的最佳方式)

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 subqueries。如果您將我的原始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 
+0

那麼你最終將模板循環寫爲'for process in record(query)'? – boatcoder