【问题标题】:Django manytomany query weird behaviorDjango manytomany 查询奇怪的行为
【发布时间】:2016-12-14 08:20:55
【问题描述】:

我有以下型号:

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如何正确下单?

更新: 还有一个问题。为什么Post.objects.annotate(s_count=Count('subscribers')).order_by‌​('-s_count', '-subscription__date_subscribed').count() 在订阅中给出 4 而不是行数?

【问题讨论】:

    标签: mysql django


    【解决方案1】:

    由于SubscriptionPostSubscriber 之间m2m 关系的直通表,当您对Subscription 模型本身的字段进行排序时,所有帖子在结果集中显示为单独的行,这就是为什么你会收到s_count=1,因为每个特定订阅者的帖子都是独一无二的。

    您需要用所有subscribers 中最新的date_subscribed 注释Post 对象,然后在注释字段上排序:

    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')) 获得的计数不同,因为此时已在结果集中获取日期的各个值。

    【讨论】:

    • 很简单。谢谢。
    • 很高兴能帮上忙。
    • 还有一个问题。为什么 Post.objects.annotate(s_count=Count('subscribers')).order_by('-s_count', '-subscription__date_subscribed').count() 在 Subscription 中给出 4 而不是行数?
    • 预期输出是什么?
    • 我认为是订阅模型中的行数,还是计算帖子模型中的行数?
    猜你喜欢
    • 2017-03-01
    • 2016-02-24
    • 2010-11-26
    • 2012-09-24
    • 2012-06-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多