Django Aggreagtion: только возвращаемое значение суммы?

У меня есть список значений, которые вы заплатили, и хотите отобразить общую оплаченную. Я использовал агрегирование и сумму для вычисления значений вместе. Проблема в том, что я просто хочу, чтобы общее значение было напечатано, но аггрегация выдает: {'amount__sum': 480.0} (480.0 - общая добавленная стоимость.

В моем представлении у меня есть:

    from django.db.models import Sum

    total_paid = Payment.objects.all.aggregate(Sum('amount'))

И чтобы показать значение на странице, у меня есть шаблон mako со следующим:

    <p><strong>Total Paid:</strong> ${total_paid}</p>

Как мне заставить его показать 480.0 вместо {'amount__sum': 480.0}?

14
02 окт. '13 в 16:54
источник поделиться
4 ответов

Я не верю, что есть способ получить только значение.

Вы можете просто сделать ${{ total_paid.amount__sum }} в своем шаблоне. Или сделайте total_paid = Payment.objects.all().aggregate(Sum('amount')).get('amount__sum', 0.00) в своем представлении.

ИЗМЕНИТЬ

Как отмечали другие, .aggregate() всегда будет возвращать словарь со всеми ключами из присутствующих агрегатов, поэтому сделать .get() в результате не нужно. Однако, если набор запросов пуст, каждое агрегированное значение будет None. Поэтому, в зависимости от вашего кода, если вы ожидаете плавать, вы можете сделать:

total_paid = Payment.objects.all().aggregate(Sum('amount'))['amount__sum'] or 0.00

21
02 окт. '13 в 16:56
источник

Метод aggregate() возвращает словарь. Если вы знаете, что возвращаете только словарь с одним входом, вы можете использовать .values()[0]:

total_paid = Payment.objects.aggregate(Sum('amount')).values()[0]

Конечный результат совпадает с ответом @jproffitt, но он избегает повторения части amount__sum, поэтому он немного более общий.

13
25 сент. '14 в 19:18
источник

Дайте ему имя, а затем попросите его:

total_paid = Payment.objects.all.aggregate(sum=Sum('amount'))['sum']

Должно быть немного читабельнее, и нет необходимости в конверсии.

8
10 июня '16 в 18:20
источник

В Python 3:

Вы можете решить эту проблему, преобразов dict_values в list:

total_paid = list(Payment.objects.aggregate(Sum('amount')).values())[0] or 0 # the or 0 is required in case the query is an empty query set.

Предыдущий код избегает использования 'column_name__sum' в качестве ключа, но в случае, если вы предпочитаете словарь:

total_paid = Payment.objects.aggregate(Sum('amount'))['amount__sum'] or 0

С точки зрения эффективности, я сделал тест с некоторыми данными, которые у меня есть, и кажется, что с помощью словарного ключа происходит быстрее:

In [9]: %timeit total = Pledge.objects.filter(user=user, group__isnull=True).aggregate(Sum('amount'))['amount__sum'] or 0
3.13 ms ± 25.1 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

In [10]: %timeit total = list(Pledge.objects.filter(user=user, group__isnull=True).aggregate(Sum('amount')).values())[0] or 0
3.22 ms ± 61.1 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

В плане удобочитаемости я считаю, что решение @mehmet является лучшим, и я также проверял его эффективность:

In [18]: %timeit Pledge.objects.filter(user=user, group__isnull=True).aggregate(sum=Sum('amount'))['sum'] or 0
3.22 ms ± 124 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
0
07 янв. '18 в 6:04
источник

Посмотрите другие вопросы по меткам или Задайте вопрос