Использование значений после Cast и Replace в Django ORM

Фиктивные данные:

field_1 price
lot 1 1,333.00
lot 1 348.39
lot 2 98.00

Цель - сложить значения цены

Поскольку цена - это строки, представляющие числа, Cast и Replace используются для удаления запятой-разделителя тысяч и выполнения суммы.

Если я хочу сделать общую сумму, это работает без проблем:

total_price = (
    myModel.objects.filter(status='Active', project_id=pid)
    .annotate(
        cleaned_total=Replace('price', Value(','), Value(''))
    )
    .annotate(float_total=Cast('cleaned_total', FloatField()))
    .aggregate(Sum('float_total'))
)

вывод итоговой_цены: {'float_total__sum': 1779.39}

Проблема в том, что я хочу сгруппировать сумму, и для этого я использую .values('field_1') и хочу, чтобы результат был примерно таким:

<QuerySet [{'field_1': 'lot 1', 'float_total__sum': 1681.39}, {'field_1': 'lot 2', 'float_total__sum': 98.0}]

Что я пробовал:

total_price_grouped = (
    myModel.objects.filter(status='Active', project_id=pid)
    .values('field_1')
    .annotate(
        cleaned_total=Replace('price', Value(','), Value(''))
    )
    .annotate(float_total=Cast('cleaned_total', FloatField()))
    .aggregate(Sum('float_total'))
)

Но, к сожалению, это дает следующий результат: {'float_total__sum': 1779.39}

Если я не использую Cast and Replace, сумма группируется правильно, как нужно, но значения с разделителем из тысячи запятых добавляются неправильно:

total_price_grouped = myModel.objects.filter(status='Active', project_id=pid).values('field_1').annotate(sum=Sum('price'))

Как я могу получить сумму, объединив values, replace и cast?

вы получаете только один результат, потому что используете агрегат

также важен порядок. сначала аннотация, затем группировка по und sum

myModel.objects.filter(status='Active', project_id=pid)
.annotate(
    cleaned_total=Replace('price', Value(','), Value(''))
)
.annotate(float_total=Cast('cleaned_total', FloatField()))
.values('field_1')
.order_by('field_1')
.annotate(grouped_totals=Sum('float_total')
)
Вернуться на верх