如何用过滤Django查询计数?

时间:2019-03-19 05:20:32

标签: 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

def latest_posts(request)
    latest_100_posts = BlogPost.objects.all()[:100]

我获得了最近的100条帖子,现在我想让每个帖子的作者,并显示其批准,待处理,被拒绝的总数

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

我考虑过的某些事情是遍历100个帖子中的每个帖子并返回计数,但效率似乎很低

for post in latest_100_posts:
    approved_count = BlogPost.objects.filter(author=post.user,status='A').count()
    pending_count = BlogPost.objects.filter(author=post.user,status='P').count()
    rejected_count = BlogPost.objects.filter(author=post.user,status='R').count()

有没有更有效的方法?我知道使用聚合计数,但不确定如何对状态ChoiceField进行子过滤

2 个答案:

答案 0 :(得分:0)

您可以使用conditional aggregation这样操作:

为此,让我们在related_name中添加BlogPost

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

然后让我们更新查询集:

from django.db.models import Count, Case, When, IntegerField

top_post_users = list(BlogPost.objects.values_list('auther_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 :(得分:0)

from django.db.models import Count

approved_count = BlogPost.objects.filter(author=post.user, status=‘A’).annotate(approved_count=Count(‘id’))
pending_count = BlogPost.objects.filter(author=post.user, status=‘P’).annotate(approved_count=Count(‘id’))
rejected_count = BlogPost.objects.filter(author=post.user, status=‘R’).annotate(approved_count=Count(‘id’))