У меня есть 3 (упрощенные для этого предложения) модели:
TaxRate(models.Model):
rate = models.DecimalField()
name = models.CharField()
@property
def friendly_name(self):
return some_string
InvoiceLine(models.Model):
invoice = models.ForeignKey('Invoice', related_name="lines")
netto = models.DecimalField()
rate = models.ForeignKey('TaxRate')
Invoice(models.Model):
no = models.CharField()
Я пытаюсь получить строки счета-фактуры, сгруппированные по taxrate__rate.
Я делаю
invoice.lines.order_by('-taxrate__rate').values('taxrate__rate')\
.annotate(
sum_netto=models.Sum('netto')
)
и я получаю список диктов с таким
[{'taxrate__rate': Decimal(7.00), 'sum_netto': Decimal(12.00)}]'
это нормально, но я хотел бы получить тот же результат с объектом TaxRate, где я могу использовать метод friendly_name
.
Есть ли способ сделать это, используя только один простой (как этот) запрос?
Я знаю, что не могу использовать .only()
.defer()
, потому что тогда он не сгруппирован по taxrate__rate, потому что поле id
обязательно для этого.
Я также не хочу делать это на стороне Python (например, цикл for для различных таксатов и затем агрегировать sum_netto или просто создавать список dicts в python из набора запросов)
мое временное решение (это ужасно, я знаю), когда self - это счет:
lines = self.lines.order_by('-taxrate__rate')\
.values('taxrate__rate', 'taxrate')\
.annotate(
sum_netto=models.Sum('netto'),
)
for idx, line in enumerate(lines):
lines[idx]['taxrate'] = TaxRate.objects.get(id=line['taxrate'])
return lines
Мое второе (и, на самом деле, лучшее на данный момент) решение (когда «Я» выставляет счет):
return TaxRate.objects\
.filter(invoiceline__invoice=self).distinct()\
annotate(
sum_netto=models.Sum('invoiceline__netto')
)
но все же это не очень идиоматично и как-то нелогично
есть ли лучший способ?