2009-12-15 63 views
4

我在用戶對象中有一個ManyToManyField,它用於映射用戶所關注的用戶。我試圖展示他們最近關注的人的子集列表。 .order_by()中是否有一個技巧可以讓我通過ManyToManyField的ID進行排序?數據在那裏,對嗎?我如何根據Django中的ManyToManyField的ID進行排序?

# (people the user is following) 
following = models.ManyToManyField(User, related_name="following", blank=True) 

theuser.following.filter(user__is_active=True).order_by("user__id") 

這會給我一個用戶列表,他們加入後會按照用戶的順序排列。我希望以下列表的順序按照用戶跟隨他們的順序進行。

+0

有趣/奇怪的問題。 ManyToMany用於執行連接的中間表的id字段很有趣,因爲...? – 2009-12-15 03:58:38

+0

請張貼一些代碼。 – czarchaic 2009-12-15 06:36:53

+2

@peter我認爲該表中的id應顯示所建立關係的順序,以便他可以完成他的「你最近遵循的:」主意。 – 2009-12-15 18:45:05

回答

0

我不確定您是否可以通過常規ManytoManyField來實現此目標。你可以嘗試明確定義中間模型。

nb:未經測試的代碼!

class Person(models.Model) 
    name = models.CharField(max_length=30) 

class FollowerRelationship(models.Model) 
    follower = models.ForeignKey(Person, related_name = following_set) 
    following = models.ForeignKey(Person, related_name = follower_set) 

然後,您可以在shell中創建以下關係,如下所示。

# Create Person objects 
>>> a = Person(name="Alice") 
>>> a.save() 
>>> b = Person(name="Bob") 
>>> b.save() 
>>> c = Person(name="Chris") 
>>> c.save() 

# Let Alice follow Chris and Bob 
>>> FollowerRelationship.objects.create(follower=a, following=c) 
>>> FollowerRelationship.objects.create(follower=a, following=b) 

您可以創建FollowerRelationship對象愛麗絲是跟隨者,通過連接表的id訂購的queryset的,用線:

>>> qs = FollowerRelationship.objects.filter(follower=a).order_by('id') 
>>> [fr.following for fr in qs] 

請注意,您通過FollowerRelationship必須循環對象,以獲得關係中的'follow'Person

您可能還想看看Django文檔中的Extra fields on many-to-many relationships,該文檔介紹瞭如何以多對多關係指定中間模型。

2

我只是找到了一種方法來做到這一點,而無需爲關係創建類。它依賴於extra功能,可讓您添加更多列以輸出。在您的例子看起來會像:

theuser.following.filter(user__is_active=True)\ 
    .extra(select={'creation_seq': 'appname_user_user_following.id'})\ 
    .order_by("creation_seq") 

注意appname_user_user_following是關係表中的Django在幕後創建名稱。它是確定性的,你可以通過元機制獲得和設置,但它對硬編碼來說非常安全。

這裏是一個的被蓋下創建了假表和列名的SQL的一個例子:

SELECT (appname_user_user_following.id) AS `creation_seq`, `appname_user`.`id` 
FROM `appname_user` INNER JOIN `appname_user_user_following` ON 
(`appname_user`.`id` = `appname_user_user_following`.`user_id`) WHERE 
`appname_user_user_following`.`user_followed_id` = 1 ORDER BY `creation_seq` ASC'; 
+0

這對我有效。你應該把代碼放在花括號後面,因爲它需要一個字典。 – Archarachne 2015-11-20 08:06:33

+1

完成。謝謝@Archarachne – 2015-11-23 17:03:55

1

實際上(至少在Django 1.10),則不需要使用extra功能而是可以直接按字段排序。只需使用自動創建的表格名稱後跟「.id」作爲參數order_by。例如。

pizza.toppings.all().order_by('appname_pizza_toppings.id')

article.tags.all().order_by('appname_article_tags.id')

對於這個特殊的問題:

theuser.following.filter(user__is_active=True)\ .order_by("appname_user_user_following.id")

許多其他的解決方案建議創建通過表自定義,並增加一個字段,但如果你只是想通過排序通過表自動生成的id然後這是沒有必要的。

相關問題