2016-12-14 62 views
1

我有以下型號:Django的多對多查詢怪異的行爲

class Post(Model): 
    word = TextField() 
    subscribers = ManyToManyField(User, related_name='subscribed', through='Subscription') 

class Subscription(Model): 
    post = ForeignKey(Post) 
    subscriber = ForeignKey(User) 
    date_subscribed = DateTimeField(default=timezone.now) 

    class Meta: 
     ordering = ('-date_subscribed',) 
     unique_together = (('post', 'subscriber')) 

我想要做的是選擇的所有帖子,用戶數量訂購他們,如果用戶的數量是相等的,爲了通過最後date_subscribed

我的輸入數據:

post1 = Post(text="post1") 
post2 = Post(text="post2") 
post3 = Post(text="post3") 
post4 = Post(text="post4") 

user1 = User(username="user1") 
user2 = User(username="user2") 
user3 = User(username="user3") 
user4 = User(username="user4") 

Subscription.objects.create(post=post1, user=user1) 
Subscription.objects.create(post=post2, user=user1) 
Subscription.objects.create(post=post3, user=user1) 
Subscription.objects.create(post=post3, user=user2) 
Subscription.objects.create(post=post3, user=user3) 
Subscription.objects.create(post=post3, user=user4) 
Subscription.objects.create(post=post4, user=user1) 
Subscription.objects.create(post=post4, user=user2) 
Subscription.objects.create(post=post4, user=user3) 

此查詢工作正常,但它不date_subscribed命令:

Post.objects.annotate(s_count=Count('subscribers')).order_by('-s_count') 

當我寫:

Post.objects.annotate(s_count=Count('subscribers')).order_by('-s_count', '-subscription__date_subscribed') 

我變得奇怪結果,我不太瞭解這種行爲。對於上面的數據,它輸出的所有文章都是s_count=1

爲什麼s_count是1?而且,如何通過最後的date_subscribed正確地訂購?

UPD: 還有一個問題。爲什麼Post.objects.annotate(s_count=Count('subscribers')).order_by‌​('-s_count', '-subscription__date_subscribed').count()給出4而不是訂閱中的行數?

回答

1

由於Subscription對於PostSubscriber之間M2M關係通過表中,當您訂購的Subscription模型本身的領域,所有的帖子在結果集中顯示爲各行,這就是爲什麼你s_count=1,因爲每個崗位與特定的訂戶是唯一的。

你需要註釋的註釋字段Post對象與所有subscribers,然後才能最新date_subscribed

posts = Post.objects.annotate(
      s_count=Count('subscribers'), 
      s_date_max=Max('subscription__date_subscribed') 
     ).order_by('-s_count', '-s_date_max') 

更新下一個問題:

如果使用count()方法它將返回Posts的數量。您可以看到它與len(queryset.values_list('s_count', 'subscription__date_subscribed'))的計數值不同,因爲此時在結果集中提取了單個日期值。

+1

很簡單。謝謝。 –

+0

很高興爲您服務。 – AKS

+0

還有一個問題。爲什麼Post.objects.annotate(s_count = Count('subscribers'))。order_by(' - s_count','-subscription__date_subscribed')。count()給出了4而不是Subscription中的行數? –