Как выполнить условную агрегацию на связанном поле модели Django "один ко многим"?
Учитывая следующие схемы моделей:
class Transaction(models.Model):
wallet = models.ForeignKey(related_name="transactions")
amount = models.DecimalField() # must be positive value
type = models.CharField(choices=[("deposit", "deposit"), ("withdrawal", "withdrawal")]
class Wallet(models.Model):
pass
Какой самый эффективный запрос Django ORM для получения баланса каждой записи кошелька в базе данных?
current_balance = sum of "amounts", where type="deposits" - sum of "amounts", where type="withdrawal"
Можно изменить поле Transaction
модели type
для хранения 1
& -1
целочисленных значений в базе данных и выполнить следующий запрос:
Wallet.objects.all().annotate(current_balance=Sum(F("transactions__amount") * F("transactions__type")))
Предположим, что мы не можем изменять столбцы или поля заданных таблиц/записей.
Мысли?
Возможно, мы можем работать с:
from django.db.models import Sum
Wallet.objects.annotate(
balance=Sum('transactions__amount', filter=Q(transactions__type='deposit')) -
Sum('transactions__amount', filter=Q(transactions__type='withdrawal'))
)
Но я бы посоветовал сделать сумму отрицательной в случае вывода средств, в этом случае мы можем просто суммировать транзакции с:
# when using negative amounts for withdrawals
from django.db.models import Sum
Wallet.objects.annotate(
balance=Sum('transactions__amount')
)