Как подсчитать объекты внешнего ключа с помощью аннотации в Django?
Привет всем!
Новичок в Django, и запутался, помощь приветствуется!
У вас три модели:
class Organization(models.Model):
organization_name = models.CharField(max_length=50)
class AppealForm(models.Model):
form_name = models.CharField(max_length=50)
class Appeal(models.Model):
organization = models.ForeignKey(Organization, on_delete=models.CASCADE)
appeal_form = models.ForeignKey(AppealForm, on_delete=models.CASCADE)
applicant_name = models.CharField(max_length=150)
Объекты модели Организация:
| organization_name |
|---|
| Organization 1 |
| Organization 2 |
Объекты модели AppealForm:
| form_name |
|---|
| In written form |
| In oral form |
Объекты модели Appeal:
| organization | appeal_form | applicant_name |
|---|---|---|
| Organization 1 | In written form | First and Last name |
| Organization 1 | In oral form | First and Last name |
| Organization 1 | In oral form | First and Last name |
| Organization 2 | In written form | First and Last name |
| Organization 2 | In oral form | First and Last name |
Я пытаюсь создать таблицу в шаблоне, например:
| Organization | Total amount of appeals | Amount of written form appeals | Amount of oral form appeals |
|---|---|---|---|
| Organization 1 | 3 | 1 | 2 |
| Organization 2 | 2 | 1 | 1 |
Содержимое таблицы должно быть получено из модели Appeal, которая отображается в шаблоне.
Вопрос: Как выглядит запрос в views.py с использованием модели Appeal?
я рекомендую вам прочитать о том, как делать сложные запросы в django из этого раздела documents. Вот как будет выглядеть ваш запрос:
from django.db.models import Count, Case, When, IntegerField
Appeal.objects
.values('organization')
.annotate(
total_appeals=Count('appeal_form'),
written_amount=Count(Case(
When(appeal_form__form_name="In written form", then=1),
output_field=IntegerField(),
)),
oral_amount=Count(Case(
When(appeal_form__form_name="In oral form", then=1),
output_field=IntegerField(),
)),
).order_by()
установите вышеуказанный запрос на значение, пройдитесь по нему и посмотрите результаты. Вы должны получить что-то вроде этого
[{'organization': 'Organization 1', 'total_appeals': 3, 'письменная_сумма': 1, 'устная_сумма': 2}, {'организация': 'Организация 2', 'total_appeals': 2, 'письменная_сумма': 1, 'oral_amount': 1}]
Объяснения:
- значения для группировки по
organization Countдля подсчета форм в этой организационной группе- мы используем
Caseдля добавленияif condition, then=1 для возврата значения (иначе возвращается null) - сумма_записи должна быть целой, поэтому мы устанавливаем ее в
output_field.
условная часть в документах https://docs.djangoproject.com/en/dev/ref/models/conditional-expressions
Почему следует использовать order_by() для группировки запросов https://docs.djangoproject.com/en/4.0/topics/db/aggregation/#interaction-with-order-by