2011-07-19 51 views
3

我使用Django編寫社交網絡應用程序,並且需要實現類似於Facebook「共同朋友」概念的功能。我有這樣一個簡單的模型:Django:根據交叉對象的數量訂購商品(共同朋友)

class Friend(models.Model): 
    user = models.ForeignKey(User) 
    guid = models.BigIntegerField() 
    name = models.TextField() 

    class Meta: 
     unique_together = ['user', 'facebook_id'] 

它代表我的網站的用戶,和他的一個朋友之間的關係。 (朋友們不一定也是用戶)的共同的朋友兩個用戶之間的數字可以作爲他們的朋友名單的交集來計算,換言之,

users = User.objects.all() 
friends = Friend.objects.filter(user=request.user) 
friend_ids = [f.guid for f in friends] 
for user in users: 
    user.mutual = Friend.objects.filter(user=user, guid__in=friend_ids).count() 

(做的更有效的方法上面將比分積分)。

我的主要問題是,計算了用戶之間的共同朋友數量,我怎麼現在可以根據當前用戶的共同朋友數量來訂購users queryset?在這種情況下,我不能將計數保存爲註釋或額外字段,因爲它依賴於正在檢查的特定用戶以及他的全部朋友的特定子集。我能否以一種巧妙的方式使用annotateextra方法?或者是一個raw sql查詢的唯一途徑?如果是這樣,怎麼樣?

總結

計算的共同朋友的數量爲每個用戶是沒有問題的。鑑於每個用戶的信息,那麼您如何根據該號碼訂購QuerySet

回答

2

不知道這是你在尋找什麼,但...

# get current users friends (assuming guid is unique for a friend?) 
user_friend_guids = Friend.objects.values_list('guid', flat=True).filter(user=user) 

# get Friend objects where user not current user, is in user_friend_list, group and count by user 
mutual_friends = Friend.objects.values('user__username') \ 
           .filter(guid__in=user_friend_guids).exclude(user=user) \ 
           .annotate(number_mutual_friends=Count('user')) \ 
           .order_by('-number_mutual_friends') 

將返回用戶名的列表與朋友,他們與用戶共享的數量,由他們分享的次數進行排序。

然後在模板:

{% for mutual_friend in mutual_friends %} 
    {{mutual_friend.user__username}} - {{mutual_friends.number_mutual_friends}} 
{% endfor %} 
+0

恐怕不太我正在尋找:我期待以便根據其共同的朋友數量User's對象'名單,而不是朋友的對象。我知道一個小小的區別,但這是給用戶帶來麻煩的排序。爲了澄清,'用戶'對象是正常的Django後端'用戶'對象,而'朋友'定義如上,並不代表實際用戶,只是我用戶的聯繫人列表中的人員。 –

+0

好的,爲了澄清以上不會返回Friend對象。它會以[{「user__username」:james,「number_mutual_friends」:10},{「user__username」:herman,「number_mutual_friends」:6}]的格式返回一個列表,所以您將得到用戶名列表(或字段你選擇),但是,正如你提到的不是用戶對象。如果它必須是用戶對象,我認爲(其他人可能會回答)它需要通過原始SQL或將共同朋友定義爲通過python的方法和順序來完成eHttp://stackoverflow.com/questions/981375/using -a-django-custom-model-method-property-in-order- – JamesO

+0

好的,謝謝。不幸的是,訂購python不會成爲一種選擇,因爲可能有10000多個用戶。但是,是的,現在想想看,你的方法看起來可能是所有必要的。我會多玩一會兒,然後回來(希望能有一個解決方案)。謝謝! –