2013-04-04 63 views
1

我在這個上真的很掙扎。 我需要能夠根據他們的評論收到的正面投票數量對我的用戶進行分類。Django sql order by

我有一個表userprofile,一個表評論和一個表likeComment。 表註釋對其用戶創建者有一個外鍵,表likeComment對喜歡的評論有一個外鍵。 要獲得正投票數的用戶接收我做的:

LikeComment.objects.filter(Q(type = 1), Q(comment__user=user)).count() 

現在我希望能夠得到所有由具有最積極的票的人排序的用戶。我怎麼做 ?我試圖使用額外和JOIN,但這並沒有去任何地方。

謝謝

回答

2

這聽起來像你想上的註釋進行過濾:

class User(models.Model): 
    pass 

class Comment(models.Model): 
    user = models.ForeignKey(User, related_name="comments") 

class Like(models.Model): 
    comment = models.ForeignKey(Comment, related_name="likes") 
    type = models.IntegerField() 

users = User \ 
    .objects \ 
    .all() 
    .extra(select = { 
     "positive_likes" : """ 
     SELECT COUNT(*) FROM app_like 
     JOIN app_comment on app_like.comment_id = app_comment.id 
     WHERE app_comment.user_id = app_user.id AND app_like.type = 1 """}) 
    .order_by("positive_likes") 
+0

感謝蒂米,我越來越瘋狂,並啓用查詢! 現在,我這樣做,我得到一個數據庫錯誤:語法錯誤或在「選擇」附近 行8:選擇計數(*)從axiom_alto_likecomment – 2013-04-04 17:33:32

+0

我明白了!這是因爲註釋,因爲某些原因,我不能註釋和額外的,所以我把所有東西都放到了extraa ^^再次感謝 – 2013-04-04 19:13:11

1

models.py

class UserProfile(models.Model): 
    ......... 

    def like_count(self): 
     LikeComment.objects.filter(comment__user=self.user, type=1).count() 

views.py

def getRanking(anObject): 
    return anObject.like_count() 

def myview(request): 
    users = list(UserProfile.objects.filter()) 
    users.sort(key=getRanking, reverse=True)  
    return render(request,'page.html',{'users': users}) 
+0

該解決方案是正確的,但如果網站每分鐘獲得大量用戶或請求,則會產生高負載 – Igor 2013-04-04 15:08:24

+0

@Igor如果需要,可以採用多種方法來減少負載。他可以使用每頁加載10個用戶的分頁。他也只能獲得前10或20個用戶,其他用戶可以搜索它。如果你真的想要問題,問題有很多解決方案。 – catherine 2013-04-04 15:15:29

+0

我是在開始時這樣做的,但我認爲額外速度更快^^謝謝無論如何,因爲您解決了我遇到的另一個問題^^ – 2013-04-04 19:14:52

0

Timmy's suggestion to use a subquery是p這是解決這類問題最簡單的方法,但子查詢幾乎不會像聯接那樣好,所以如果你有很多用戶,你可能會發現你需要更好的性能。

所以,重新使用蒂米的車型:

class User(models.Model): 
    pass 

class Comment(models.Model): 
    user = models.ForeignKey(User, related_name="comments") 

class Like(models.Model): 
    comment = models.ForeignKey(Comment, related_name="likes") 
    type = models.IntegerField() 

您想查詢看起來像這樣在SQL:

SELECT app_user.id, COUNT(app_like.id) AS total_likes 
FROM app_user 
LEFT OUTER JOIN app_comment 
      ON app_user.id = app_comment.user_id 
LEFT OUTER JOIN app_like 
      ON app_comment.id = app_like.comment_id AND app_like.type = 1 
GROUP BY app_user.id 
ORDER BY total_likes DESCENDING 

(如果您的實際User模型已經不僅僅是id多個字段,然後您需要將它們全部包含在SELECTGROUP BY子句中。)

Django的對象關係映射系統不提供表達此查詢的方式。 (據我所知 - 我會很高興被告知否則! - 它只支持在一個連接上的聚合,而不是在這裏的兩個連接上)。但是當ORM不完全適合工作時,你總是可以運行一個raw SQL query,像這樣:

sql = ''' 
    SELECT app_user.id, COUNT(app_like.id) AS total_likes 
    # etc (as above) 
''' 
for user in User.objects.raw(sql): 
    print user.id, user.total_likes 
0

我相信這可以用Django的查詢集來實現:

User.objects.filter(comments__likes__type=1)\ 
    .annotate(lks=Count('comments__likes'))\ 
    .order_by('-lks') 

這裏唯一的問題是,這個查詢將缺席用戶元起。來自@ gareth-rees,@ timmy-omahony和@Catherine的代碼也將包含0位用戶。

+0

謝謝我使用了@ timmy-omahony,它工作。謝謝 – 2013-04-04 19:14:03