2016-12-14 6 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')) 

私がやりたいことは、すべての記事を選択する加入者の数によってそれらを注文することで、加入者数は、ORDER BY等しい場合最後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: もう1つ質問があります。なぜPost.objects.annotate(s_count=Count('subscribers')).order_by‌​('-s_count', '-subscription__date_subscribed').count()はサブスクリプションの行数の代わりに4を与えますか? Subscription以来

答えて

1

PostSubscriber間M2M関係するためのスルーのテーブルで、あなたはSubscriptionモデル自体のフィールドに注文すると、すべての記事は、結果セット内の個々の行として表示され、あなたが各ポストのでs_count=1を得る理由です特定の加入者は一意である。あなたが使用している場合は

:次の質問には

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

UPDATE:あなたは、最新の注釈付きフィールド上の全てのsubscribers、その後、注文のdate_subscribedがでPostオブジェクトに注釈を付ける必要がある

count()メソッドは、Postsの番号を返します。現時点では、日付の個々の値が結果セットに取り込まれているため、len(queryset.values_list('s_count', 'subscription__date_subscribed'))から得られるカウントとは異なることがわかります。

+1

かなり簡単です。ありがとうございました。 –

+0

助けになるのはうれしいです。 – AKS

+0

もう1つ質問があります。なぜ、Post.objects.annotate(s_count = Count( 'subscribers')))。order_by( ' - s_count'、 '-subscription__date_subscribed')。 –