Django计算多个对象中2个字段的均值

时间:2020-01-15 10:14:10

标签: django math django-models django-views aggregate

我正在尝试做一个非常简单的数学问题,但是我不知道如何将其转换为python。基本上,我需要基于多个“购买”条目来计算交易的平均进入价格。要做的就是计算

∑ (entry.amount * entry.price) / ∑ (entry.amount)

最后应该是变量“ total_entry_price2”。

  1. 我的计算哪里出错了?如何将所有∑加在一起?
  2. 这是最好的方法吗?

models.py

class Trade(models.Model):
    ... 

class Entry(models.Model):
    ...
    trade = models.ForeignKey(Trade, on_delete=models.CASCADE)
    amount = models.FloatField()
    price = models.FloatField()
    entry_type = models.CharField(max_length=3, choices=ENTRY_TYPE_CHOICES, default=BUY)

views.py

@login_required
def trade_detail_view(request, pk):
    logger.info('trade detail view')
    if request.method == 'GET':
        trade = get_object_or_404(Trade, pk=pk)
        entries = Entry.objects.filter(trade=trade)
        entries_buy = Entry.objects.filter(trade=trade, entry_type="buy")
        patterns = Pattern.objects.filter(trade=trade)

        for entry in entries_buy:
            total_entry_price = Sum(entry.amount * entry.price)
            total_entry_price2 = total_entry_price / entries_buy.aggregate(Sum('amount'))
            print(total_entry_price2)

        context = {
            'trade': trade,
            'entries': entries,
            'patterns': patterns,
            'max_amount': entries_buy.aggregate(Sum('amount')),
            'total_fees': entries.aggregate(Sum('fee')),
            'entry_price': entries_buy.aggregate(Avg('price'))
        }

当前终端打印:

Sum(Value(60.0)) / Value({'amount__sum': 40.0})
Sum(Value(10.0)) / Value({'amount__sum': 40.0})

示例数据

enter image description here

正确的答案应该是1.75美元

(30 * 2 + 10 * 1) / 40 = 1.75

最终解决方案(由Oleg Russkin的答案添加)

我所做的修订如下:

total_entry_cost = entries_buy.annotate(
    s=F('amount') * F('price')
).aggregate(
    total_entry_cost=ExpressionWrapper(
        Sum(
            Cast('s', output_field=models.FloatField())
        ) / Sum('amount'),
        output_field=models.FloatField()
    )
)['total_entry_cost']
print(total_entry_cost)

1 个答案:

答案 0 :(得分:2)

用于计算所需值的示例查询。

如果function scrollTime(){ location.href = "#"; location.href = "#projects"; window.scrollBy(0, -108); } 的结果是浮点数而不是Cast(),则可以避免

Sum浮点数。

integer

OP更新的答案

这个答案几乎使我们一路走好。我不清楚我在寻找的确切答案是什么。我在末尾更新了我的问题以反映它。

我所做的修订如下:

from django.db import models
from django.db.models import ExpressionWrapper, F, Sum
from django.db.models.functions import Cast


total_entry_price2 = Entry.objects.annotate(
    s=F('amount')+F('price')
).aggregate(
    price2=ExpressionWrapper(
        Sum(
            Cast('s',output_field=models.FloatField())
        ) / Sum('amount'),
        output_field=models.FloatField()
    )
)['price2']

# Actual result of the query is dictioanry
# so we get the key
# {'price2': 0.59633706227207}