我有以下型号:
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而不是行数?
答案 0 :(得分:1)
由于Subscription
是Post
和Subscriber
之间m2m关系的直通表,当您在Subscription
模型本身的字段上订购时,所有帖子都显示为结果集中的各个行以及您获得s_count=1
的原因,因为每个具有特定订阅者的帖子都是唯一的。
您需要使用所有Post
中的最新date_subscribed
注释subscribers
个对象,然后在带注释的字段中进行排序:
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'))
的计数不同,因为此时已在结果集中提取日期的各个值。