Django аннотирование по нескольким записям forignkeys
Я работаю над системой KPI, в которой каждый менеджер может задавать конкретные вопросы каждому пользователю и отвечать на них каждый месяц от 1 до 10 У нас есть 4 отдела, и каждый отдел говорит, что у него есть 4 вопроса эти ответы должны быть вычислены, чтобы вернуть % количество для каждого отдела
Модели
# question to answer every month
class Question(models.Model):
department = models.CharField(max_length=100, choices=USER_TYPE)
question = models.CharField(max_length=100)
def __str__(self):
return f"{self.question}"
# create every 01-month celery
class Kpi(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE, related_name="kip_for")
created_at = models.DateField()
class Meta:
unique_together = ("user", "created_at")
def __str__(self):
return f"{self.user} for Month {self.created_at.month}"
# group the answers by department
class DepartmentsKPI(models.Model):
department = models.CharField(max_length=100, choices=USER_TYPE)
kpi = models.ForeignKey(
Kpi, on_delete=models.CASCADE, related_name="department_kpi"
)
class Answer(models.Model):
question = models.ForeignKey(
Question, on_delete=models.CASCADE, related_name="answer_for"
)
score = models.PositiveSmallIntegerField(default=0)
comment = models.TextField(null=True, blank=True)
kpi_answers = models.ForeignKey(
DepartmentsKPI,
on_delete=models.CASCADE,
related_name="department_answers",
)
Проблема в том, что когда я применяю аннотацию к модели KPI для суммирования баллов ответов для каждого отдела, результат становится несгруппированным, поэтому мне приходится группировать их по уникальному значению, в моем случае по имени пользователя
def get_kpi_range(*, year, month):
queryset = (
KPIRepository.filter_kpis(
created_at__year=year,
created_at__month=month,
)
.prefetch_related("department_kpi__department_answers")
.annotate(
score=Sum("department_kpi__department_answers__score")
/ Count("department_kpi__department_answers"),
department=F("department_kpi__department"),
)
.values("id", "score", "department", username=F("user__username"))
)
grouped = [
{"username": username, "kpis": list(instances)}
for username, instances in itertools.groupby(queryset, lambda x: x["username"])
]
return grouped
Однако это не позволяет обрабатывать несколько записей для одного и того же пользователя. Если я запрашиваю все KPI за один год, результат становится беспорядочным.
Кроме того, если я хочу построить графики, я не могу вернуть данные для каждого пользователя, сгруппированные по каждому месяцу года
Текущий результат с grouped
выше
[
{
"username": "xxxxx",
"kpis": [
{
"department": "HR",
"score": 5
},
{
"department": "IT",
"score": 6
},
{
"department": "QUALITY",
"score": 4
},
{
"department": "WFM",
"score": 6
}
]
},
{
"username": "ahmed",
"kpis": [
{
"department": "IT",
"score": 6
}
]
}
]
Без grouped
[
[
{
"id": 7,
"score": 5,
"department": "HR",
"username": "xxx"
},
{
"id": 7,
"score": 6,
"department": "IT",
"username": "xxx"
},
{
"id": 7,
"score": 4,
"department": "QUALITY",
"username": "xxx"
},
{
"id": 7,
"score": 6,
"department": "WFM",
"username": "xxx"
},
{
"id": 8,
"score": 6,
"department": "IT",
"username": "ahmed"
}
]
]