python - tag - Django Aggreagtion: ¿Valor de retorno de la suma solamente?
escape django (4)
Dale un nombre y luego pídelo:
total_paid = Payment.objects.all.aggregate(sum=Sum(''amount''))[''sum'']
Debería ser un poco más legible, y no hay necesidad de conversión.
Tengo una lista de valores pagados y quiero mostrar el total pagado. He usado la agregación y la suma para calcular los valores juntos. El problema es que solo quiero que se imprima el valor total, pero se imprime la agregación: {''amount__sum'': 480.0}
(480.0 es el valor total agregado).
En mi opinión, tengo:
from django.db.models import Sum
total_paid = Payment.objects.all.aggregate(Sum(''amount''))
Y para mostrar el valor en la página, tengo una plantilla de mako con lo siguiente:
<p><strong>Total Paid:</strong> ${total_paid}</p>
¿Cómo puedo hacer que muestre 480.0
lugar de {''amount__sum'': 480.0}
?
El método aggregate()
devuelve un diccionario. Si sabe que solo está devolviendo un diccionario de una sola entrada, podría usar .values()[0]
.
En Python 2 :
total_paid = Payment.objects.aggregate(Sum(''amount'')).values()[0]
En Python 3 , (gracias @lmiguelvargasf) esto tendrá que ser:
total_paid = list(Payment.objects.aggregate(Sum(''amount'')).values())[0]
El resultado final es el mismo que la respuesta de @jproffitt, pero evita repetir la amount__sum
parte de amount__sum
, por lo que es un poco más genérico.
No creo que haya una manera de obtener solo el valor.
Solo puedes hacer ${{ total_paid.amount__sum }}
en tu plantilla. O haga total_paid = Payment.objects.all().aggregate(Sum(''amount'')).get(''amount__sum'', 0.00)
en su vista.
EDITAR
Como han señalado otros, .aggregate()
siempre devolverá un diccionario con todas las claves de los agregados presentes, por lo que no es necesario hacer .get()
en el resultado. Sin embargo, si el conjunto de consultas está vacío, cada valor agregado sería None
. Entonces, dependiendo de tu código, si estás esperando un flotador, podrías hacer:
total_paid = Payment.objects.all().aggregate(Sum(''amount''))[''amount__sum''] or 0.00
En Python 3 :
Puedes resolverlo convirtiendo los dict_values
en una 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.
El código anterior evita el uso de ''column_name__sum''
como clave, pero en caso de que prefiera la forma del diccionario:
total_paid = Payment.objects.aggregate(Sum(''amount''))[''amount__sum''] or 0
En términos de eficiencia, hice una prueba con algunos datos que tengo, y parece que usar la clave del diccionario es más rápido:
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)
En términos de legibilidad, creo que la solución de @ mehmet es la mejor, y también he probado su eficiencia:
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)