Как объединить два набора запросов Django - PullRequest
1 голос
/ 20 марта 2019

Я пытаюсь получить список последних 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 ​​('title' ,mitted_count ',' pending_count ',' reject_count ')

... и это работает, но возвращает больше, чем последние 100 сообщений, поэтому я думаю, что он получает все сообщения для этих пользователей и общее количество.

1 Ответ

2 голосов
/ 20 марта 2019

В конечном итоге, вам нужен список BlogPosts:

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...