Using model methods in aggregates

I am trying to use a model method in an aggregated django request. I am not sure that this is possible, and I may be mistaken.

Here is the model I want to request.

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 

The getHDSV method returns the reporting metric used inside where the application is located. I want to combine the metric in the total amount for the month between the date.

I am not an aggregate / annotate master. My attempts so far have not yielded the results that I got after.

I ended up Bookings between the dates and then looped around the results and counted the reporting block into the dictionary by calling the getHDSV method for each iteration. Of course, the resulting dictionary is not sorted as we would like. Therefore, I now seek help.

Given the way metrics are generated, can I call a model method when aggregating data in a query? Or should I use the HDSVunits dictionary when creating the aggregate ? Or is there a better way?

Thanks.

+7
source share
2 answers

You have a rather complicated setup, it would be easier to have an HDSVunits in the Price model to simplify access to queries.

The best I can come up with is something like this:

 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(), ) ) ) 

If the HDSV value was saved as a field in the Price model, you could simply do:

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

On the side of the note, you should really consider the following Python naming conventions that would make it easier for other Python developers to help you.

+1
source

If the data returned by getHDSV not from the database, then aggregate and annotate cannot be used to collect statistics on it.

0
source

All Articles