2009-12-08 35 views
0

所以我在這裏有一個相當涉及的SQL查詢。在Django中執行PostgreSQL左外連接和CASE

SELECT links_link.id, links_link.created, links_link.url, links_link.title, links_category.title, SUM(links_vote.karma_delta) AS karma, SUM(CASE WHEN links_vote.user_id = 1 THEN links_vote.karma_delta ELSE 0 END) AS user_vote 
FROM links_link 
LEFT OUTER JOIN auth_user ON (links_link.user_id = auth_user.id) 
LEFT OUTER JOIN links_category ON (links_link.category_id = links_category.id) 
LEFT OUTER JOIN links_vote ON (links_vote.link_id = links_link.id) 
WHERE (links_link.id = links_vote.link_id) 
GROUP BY links_link.id, links_link.created, links_link.url, links_link.title, links_category.title 
ORDER BY links_link.created DESC 
LIMIT 20 

我所有的關係都很好(我認爲),這個查詢完美的作品,當我在我的Navicat運行PostgreSQL的,但把它變成東西Django的可以使用已經相當的挑戰。我正在使用pre-alpha 1.2開發版本(來自Subversion版本庫),所以我有來自文檔的全套工具。

這裏是我的模型笑容:

class Category (models.Model): 
    created = models.DateTimeField(auto_now_add = True) 
    modified = models.DateTimeField(auto_now = True) 
    title = models.CharField(max_length = 128) 

    def __unicode__(self): 
     return self.title 

class Link (models.Model): 
    category = models.ForeignKey(Category) 
    user = models.ForeignKey(User) 
    created = models.DateTimeField(auto_now_add = True) 
    modified = models.DateTimeField(auto_now = True) 
    fame = models.PositiveIntegerField(default = 1) 
    url = models.URLField(max_length = 2048) 
    title = models.CharField(max_length = 256) 
    active = models.BooleanField(default = True) 

    def __unicode__(self): 
     return self.title 

class Vote (models.Model): 
    link = models.ForeignKey(Link) 
    user = models.ForeignKey(User) 
    created = models.DateTimeField(auto_now_add = True) 
    modified = models.DateTimeField(auto_now = True) 
    karma_delta = models.SmallIntegerField(default = 1) 

    def __unicode__(self): 
     return str(self.karma_delta) 

如何,我能轉

def latest(request): 
    links = Link.objects.all().order_by('-created')[:20] 
    return render_to_response('links/list.html', {'links': links}) 

向上述查詢?

我只能使用之類的東西取得一些進展,但如何解決我對CASE的使用超出了我的想象。任何幫助將非常感激。我總是喜歡在框架的內置ORM中工作,但是如果需要原始SQL ...

回答

3

我沒有時間嘗試完整翻譯該查詢,但如果CASE是您的主要絆腳石塊,我現在可以告訴你它不是本地支持的,你需要使用一個調用.extra()與一些原始的SQL。例如:

.extra(select={'user_vote': 'SUM(CASE WHEN links_vote.user_id = 1 THEN links_vote.karma_delta ELSE 0 END')}) 

但是,如果此查詢正常工作,爲什麼還要將它翻譯成ORM?只需grab a cursor and run it as a SQL query。 Django的ORM故意不是100%的解決方案,這是暴露原始遊標API的原因。

更新:自從Django 1.2以來,還有Manager.raw()讓您可以進行原始SQL查詢並返回模型對象(感謝Van Gale)。

+1

還有QuerySet.raw()進入1.2:http://simonwillison.net/static/2009/djugl-december.html – 2009-12-08 16:13:49