如何合并两个查询集Django

时间:2019-03-20 19:09:48

标签: python django

我正在尝试获取最近100条帖子的列表,以及该帖子用户的已批准,待处理和已拒绝帖子的总数。

models.py

class BlogPost(models.Model):
    POST_STATUSES = (
                    ('A', 'Approved'),
                    ('P', 'Pending'),
                    ('R', 'Rejected')
                    )
    author = models.ForeignKey(User)
    title = models.CharField(max_length=50)
    description = models.TextField()
    status = models.ChoiceField(max_length=1, choices=POST_STATUSES)

views.py

现在我像这样得到汇总计数,但是我对如何将计数与帖子标题合并感到困惑

top_post_users = list(BlogPost.objects.values_list('user_id', flat=True))[:100]
users =  User.objects.filter(pk__in=top_post_users).annotate(approved_count=Count(Case(When(user_posts__status="A", then=1),output_field=IntegerField()))).annotate(pending_count=Count(Case(When(user_posts__status="P", then=1),output_field=IntegerField()))).annotate(reject_count=Count(Case(When(user_posts__status="R", then=1),output_field=IntegerField())))
users.values('approved_count', 'pending_count', 'reject_count')

这是我想要的结果:

  • 职务标题,作者1、10、5、1
  • 帖子标题2,作者2、7、3、1
  • 帖子标题3,作者1、10、5、1

如何将返回的计数与标题合并?

我知道我可以使用for循环并附加每个循环,但是出于效率考虑,我认为这不是正确的方法。有没有使用Django数据库ORM的更有效方法?

我已经尝试过了

users.values(“标题”,“已批准的计数”,“待审核的计数”,“拒绝的计数”)

...并且行得通,但返回的信息超过了最近的100条,所以我认为它正在获取这些用户的所有帖子和总计的信息。

1 个答案:

答案 0 :(得分:2)

最终,您需要一个BlogPost列表:

main_qs = BlogPost.objects
# add filters, ordering etc. of the posts

,您不仅要在帖子标题旁边显示作者,还要在带有注释计数的文章中丰富作者信息。

from django.db.models import OuterRef, Subquery, Count

# you need subqueries to annotate the blog posts
base_sub_qs = BlogPost.objects.filter(author__pk=OuterRef('author__pk'))

# add subqueries for each count
main_qs = main_qs.annotate(
    user_approved_count=Subquery(base_sub_qs.filter(status="A").annotate(
            c=Count('*')).values('c'), output_field=IntegerField()),
    user_pending_count=Subquery(base_sub_qs.filter(status="P").annotate(
            c=Count('*')).values('c'), output_field=IntegerField()),
    user_rejected_count=Subquery(base_sub_qs.filter(status="R").annotate(
            c=Count('*')).values('c'), output_field=IntegerField()),
)

然后您可以在模板中访问它们:

{% for post in posts %}
    {{ post.title }}
    {{ post.author.get_full_name }}
    approved: {{ post.user_approved_count }}
    pending: {{ post.user_pending_count }}
    rejected: {{ post.user_rejected_count }}
{% endfor %}

文档:https://docs.djangoproject.com/en/2.1/ref/models/expressions/#subquery-expressions