Использование методов модели в агрегатах - PullRequest
9 голосов
/ 11 сентября 2011

Я пытаюсь использовать метод модели в агрегированном запросе django. Я не уверен, возможно ли это, и могу ошибаться.

Вот модель, которую я хочу запросить.

class ClassNumbers(models.Model):
   """
   The class year level and number inline model for a booking
   """
   booking = models.ForeignKey('Booking')
   yearLevel = models.CharField(max_length=10, choices=YEAR_CHOICES, verbose_name='Year Level')
   numberOfStudents = models.IntegerField(verbose_name='Number of Students') 

class Booking(models.Model):
   # A shorter version of the model
   date = models.DateField()
   institution = models.ForeignKey(Institution)

   def getStudentTotal(self):
      # Total class numbers
      classes = ClassNumbers.objects.filter(booking=self.id)
      classTotal = 0
      if ( classes ):
          for c in classes:
              classTotal += c.numberOfStudents
      return classTotal

   def getHDSV(self):
      HDSVunits = {
                'Full-Day': 2.0,
                'Half-Day AM': 1.0,
                'Half-Day PM': 1.0,
                'Three-Quarter Day': 1.5,
                '1 Hour': 0.5,
                'Custom': 1.0,
                }
      numStudents = self.getStudentTotal()
      result = numStudents * HDSVunits[self.price.name]
      return result

Метод getHDSV возвращает метрику отчетности, используемую внутри, где живет приложение. Я хочу объединить показатель в итоговое значение за месяц между периодами дат.

Я не aggregate / annotate мастер. Мои попытки пока не дали результатов, к которым я стремлюсь.

В конечном итоге я запросил Bookings между указанными датами, а затем перебрал результаты и перевел отчетную единицу в словарь, вызывая метод getHDSV каждую итерацию. Конечно, полученный словарь отсортирован не так, как мне бы хотелось. Поэтому я сейчас обращаюсь за помощью.

Учитывая способ генерации метрики, можно ли вызвать метод модели при агрегировании данных в запросе? Или я должен использовать словарь HDSVunits при создании aggregate? Или есть лучший способ?

Спасибо.

Ответы [ 2 ]

2 голосов
/ 25 июля 2016

У вас довольно сложная настройка, может быть проще иметь отображение HDSVunits для модели Price, чтобы упростить доступ к ним в запросах.

Лучшее, что я могу придумать, это что-то вроде этого:

Booking.objects.aggregate(
    hdsv=(
        Sum('classnumbers__numberofstudents') * 
        Case(
            When(price__name='Full-Day', then=2.0),
            When(price__name='Half-Day AM', then=1.0),
            When(price__name='Full-Day PM', then=1.0),
            When(price__name='Three-Quarter Day', then=1.5),
            When(price__name='1 Hour', then=0.5),
            When(price__name='Custom', then=1.0),
            output_field=FloatField(),
        )
    )
)

Если значение HDSV было сохранено в виде поля на модели Price, вы можете просто сделать:

Booking.objects.aggregate(
    hdsv=Sum('classnumbers__numberofstudents') * F('price__hdsv'))

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

0 голосов
/ 30 января 2013

Если данные, возвращаемые getHDSV, не из базы данных, то aggregate и annotate не смогут использоваться для сбора статистики по ним.

...