Django: как аннотировать на основе другой аннотации или выполнять операции над аннотацией - PullRequest
5 голосов
/ 21 ноября 2011

Итак, я делаю что-то, что организует школьное расписание.Школа организована таким образом, что классы остаются вместе в одной комнате, и учитель перемещается, расписание меняется каждый день, и не все учителя или классы находятся в здании в одно и то же время, а некоторыеучителей очень привередливы, когда они преподают.

У меня есть эти модели:

class Teacher(models.Model):
    christian_name = models.CharField(max_length=200)
    family_name = models.CharField(max_length=200)
    ...

class TeacherAvailableHour(models.Model):
    teacher = models.ForeignKey('Teacher')

class Requirement(models.Model):
    ...
    teacher = models.ForeignKey('Teacher')
    per_week = models.PositiveIntegerField()
    ...

Поэтому я пытаюсь сначала составить расписание для самых требовательных учителей, а именноте с наименьшим соотношением между тем, когда они могут преподавать (общее количество «TeacherAvailableHour») и количеством часов, которое они должны преподавать (сумма всех «Requirement.per_week» учителя).

ВДругими словами, мне нужно, чтобы "order_by" это соотношение.Я не могу думать о том, как это сделать.Попробовал это:

Teachers=Teacher.objects.annotate(availability=(Count('teacheravailablehour') / Sum('requirement__per_week')).order_by('availability')

Это взрывается с ошибкой, конечно.Я также попробовал что-то вроде двойной аннотации:

Teachers=Teacher.objects.annotate(availability=Count('teacheravailablehour')).annotate(required=Sum('requirement__per_week')).annotate(availRatio=(('availability') / ('required')).order_by('-availRatio')

Каков наилучший способ сделать это?Это вообще возможно?

1 Ответ

1 голос
/ 11 декабря 2011

Вы не можете рассчитать такой коэффициент, используя метод аннотирования. Вам необходимо использовать метод extra, предоставляемый API QuerySet. Хотя поиск с использованием extra не рекомендуется, поскольку он не переносим между механизмами БД, иногда он является лучшим (или единственным) вариантом для выполнения таких сложных запросов.

Предполагая, что все модели, на которые вы ссылаетесь, находятся в приложении с именем schedules, и вы не изменили имена таблиц с помощью атрибута db_table в метаклассах ваших моделей , поиск будет выглядеть примерно так: это:

availability_sql = "(select count(*) from schedules_teacheravailablehour where schedules_teacheravailablehour.teacher_id=schedules_teacher.id) * 1.0"
required_hrs_sql = "(select sum(per_week) from schedules_requirement where schedules_requirement.teacher_id=schedules_teacher.id)"
Teacher.objects.extra(select={"ratio":"%s/%s" %(availability_sql, required_hrs_sql)}).order_by("-ratio")
...