1

I'm trying to annotate sum of fields in related set:

My models:

class Report(models.Model):

class ReportCommissionPosition(models.Model):
    report = models.ForeignKey(Report)
    reservation = models.OneToOneField("reservations.Reservation")

class Reservation(models.Model):

class Payment(models.Model):
    amount = models.DecimalField(max_digits=10, decimal_places=2)
    reservation = models.ForeignKey('reservations.Reservation')
    PAYMENT_TYPES=(
        ('TRANS', 'TRANS'),
        ('SELL', 'SELL'),
    payment_accounting_type = models.CharField(max_length=50, choices=PAYMENT_TYPES)

I need to annotate each position of report.reportcommissionposition_set with two fields:

trans_amount - Sum of all the payments with payment accounting type == 'SELL' (through reservation => payment) sum_amount - Sum of all the payments with payment accounting type == 'TRANSFER' (through reservation => payment)

I have tried:

for position in commission_position:
    position.sell_pay = position.reservation.payment_set.filter(payment_accounting_type='SELL').aggregate(amount=Sum('amount'))['amount']

But this creates new query for every element.

Any thoughts?

1 Answer 1

3

You can annotate these with:

myreport.reportcommissionposition_set.annotate(
    trans_amount=Sum(
        'reservation__payment__amount',
        filter=Q(reservation__payment__type='SELL')
    ),
    sum_amount=Sum(
        'reservation__payment__amount',
        filter=Q(reservation__payment__type='TRANS')
    )
)

the ReportCommissionPosition objects of myreport will have two extra fields: .trans_amount and .sum_amount with the sums of the SELL and TRANS payments respectively.

Sign up to request clarification or add additional context in comments.

1 Comment

Thank you Willem for sharing you knowledge! You made my day! I really apprecciate this! Optimisation note for anyone interested: I have added select_related('reservation') to the query, to reduce number of db queries

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.