Я пытаюсь аннотировать модель Django, вычисляя нетривиальное выражение, используя свойство ManyToManyField
в модели.
Ситуацию можно перевести в следующую простую примерную структуру: «платежи», которые следует разделить между несколькими «компаниями» в соответствии с их относительными размерами. Какие компании участвуют в данном платеже, сохраняется как ManyToManyField
:
class Company:
relative_size = models.DecimalField() ## can be assumed to add up to 1 among all companies
class Payment(models.Model):
companies = models.ManyToManyField(Company, related_name='payments', blank=True)
amount = models.DecimalField()
. Сейчас я пытаюсь запросить общую сумму, в которой участвовала каждая компания. Если доля была одинаковой в каждом из платежи, это будет так же просто, как
companies = Company.objects.annotate(total_payments=Sum(F('payments__amount')*F('relative_size')))
for company in companies:
print("Company %s: %s" (str(company), total_payments))
Но как это сделать в случае, когда мне нужно рассчитать правильную долю для каждого платежа, на основе которого участвовали компании? Я подозреваю, что должен использовать Subquery
, но не смог адаптировать примеры из документации к моему случаю.
PS: В качестве обходного пути я реализовал это в "Python", а не в запросах как следует:
payments_annotated = Payment.objects.annotate(sum_involved_companies_sizes=Sum(F('companies__relative_size')))
companies = Company.objects.all()
for c in companies:
c.sum = Decimal('0.0')
for p in payments_annotated.filter(companies__id=c.id):
c.sum += p.amount * c.relative_size/p.sum_involved_companies_sizes
Но я думаю, что это должно быть возможно и более эффективно в системе запросов, поэтому я надеюсь, что эксперт может помочь? Спасибо!