J'ai une liste de valeurs payées et je souhaite afficher le total payé. J'ai utilisé l'agrégation et la somme pour calculer les valeurs ensemble. Le problème est que je veux juste que la valeur totale soit imprimée, mais l'aggrégation affiche: {'amount__sum': 480.0}
(480,0 étant la valeur ajoutée totale.
À mon avis, j'ai:
from Django.db.models import Sum
total_paid = Payment.objects.all.aggregate(Sum('amount'))
Et pour afficher la valeur sur la page, j'ai un modèle mako avec ce qui suit:
<p><strong>Total Paid:</strong> ${total_paid}</p>
Comment pourrais-je le faire montrer 480.0
au lieu de {'amount__sum': 480.0}
?
Je ne crois pas qu'il existe un moyen d'obtenir uniquement la valeur.
Vous pouvez simplement faire ${{ total_paid.amount__sum }}
Dans votre modèle. Ou faites total_paid = Payment.objects.all().aggregate(Sum('amount')).get('amount__sum', 0.00)
dans votre vue.
MODIFIER
Comme d'autres l'ont souligné, .aggregate()
renverra toujours un dictionnaire avec toutes les clés des agrégats présents, donc .get()
sur le résultat n'est pas nécessaire. Cependant, si l'ensemble de requêtes est vide, chaque valeur agrégée serait None
. Donc selon votre code, si vous attendez un flottant, vous pouvez faire:
total_paid = Payment.objects.all().aggregate(Sum('amount'))['amount__sum'] or 0.00
Donnez-lui un nom puis demandez-le:
total_paid = Payment.objects.all.aggregate(sum=Sum('amount'))['sum']
Devrait être un peu plus lisible et aucune conversion n'est nécessaire.
La méthode aggregate()
renvoie un dictionnaire. Si vous savez que vous ne renvoyez qu'un dictionnaire à entrée unique, vous pouvez utiliser .values()[0]
.
Dans Python 2:
total_paid = Payment.objects.aggregate(Sum('amount')).values()[0]
Dans Python, (merci @lmiguelvargasf), cela devra être:
total_paid = list(Payment.objects.aggregate(Sum('amount')).values())[0]
Le résultat final est le même que la réponse de @ jproffitt, mais il évite de répéter le amount__sum
part, c'est donc un peu plus générique.
Dans Python:
Vous pouvez le résoudre en convertissant le dict_values
vers un 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.
Le code précédent évite d'utiliser 'column_name__sum'
comme clé, mais si vous préférez la méthode du dictionnaire:
total_paid = Payment.objects.aggregate(Sum('amount'))['amount__sum'] or 0
En termes d'efficacité, j'ai fait un test avec certaines données dont je dispose, et il semble que l'utilisation de la clé du dictionnaire soit plus rapide:
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 termes de lisibilité, je pense que la solution de @ mehmet est la meilleure, et j'ai également testé son efficacité:
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)