Django: Hitung Jumlah nilai kolom melalui query

93

Saya punya model

class ItemPrice( models.Model ):
     price = models.DecimalField ( max_digits = 8, decimal_places=2 )
     ....

Saya mencoba ini untuk menghitung jumlah pricedalam queryset ini:

items = ItemPrice.objects.all().annotate(Sum('price'))

apa yang salah dalam pertanyaan ini? atau adakah cara lain untuk menghitung Jumlah pricekolom?

Saya tahu ini dapat dilakukan dengan menggunakan for loop di queryset tetapi saya membutuhkan solusi yang elegan.

Terima kasih!

Ahsan
sumber
Apakah ini menjawab pertanyaan Anda? Pertanyaan Django SUM?
Flimm

Jawaban:

197

Anda mungkin sedang mencari aggregate

from django.db.models import Sum

ItemPrice.objects.aggregate(Sum('price'))
# returns {'price__sum': 1000} for example
MattH
sumber
1
Bagaimana saya bisa menghitung total yang harganya = 5000?
Anuj Sharma
6
Ingat mengembalikan kamus bukan float / integer misalnya {'price__sum':1000}. Bisa mendapatkan float / integer denganyourdict['price__sum']
Josh
35

Anotasi menambahkan bidang ke hasil:

>> Order.objects.annotate(total_price=Sum('price'))
<QuerySet [<Order: L-555>, <Order: L-222>]>

>> orders.first().total_price
Decimal('340.00')

Agregat mengembalikan sebuah dict dengan hasil yang diminta:

>> Order.objects.aggregate(total_price=Sum('price'))
{'total_price': Decimal('1260.00')}
Ibrohim Ermatov
sumber
Saya menghargai Anda menunjukkan bagaimana menentukan keyuntuk menyimpan jumlah tersebut value.
MikeyE
32

Gunakan .aggregate(Sum('column'))['column__sum']reefer contoh saya di bawah ini

sum = Sale.objects.filter(type='Flour').aggregate(Sum('column'))['column__sum']
ugali lembut
sumber
5

Dengan menggunakan cProfile profiler , saya menemukan bahwa dalam lingkungan pengembangan saya, lebih efisien (lebih cepat) untuk menjumlahkan nilai-nilai daftar daripada menggunakan agregat Sum(). misalnya:

sum_a = sum([item.column for item in queryset]) # Definitely takes more memory.
sum_b = queryset.aggregate(Sum('column')).get('column__sum') # Takes about 20% more time.

Saya menguji ini dalam konteks yang berbeda dan sepertinya menggunakan aggregateselalu lebih lama untuk menghasilkan hasil yang sama. Meskipun saya curiga mungkin ada keuntungan dari segi memori untuk menggunakannya daripada menjumlahkan daftar.

UncleSaam
sumber
1
Atau, menggunakan ekspresi pembangkit bukannya daftar: sum_a = sum(item.column for item in queryset). Satu-satunya perbedaan adalah []s dihapus . Ini menghemat ruang memori untuk menghitung seluruh daftar sebelum sum()mengulanginya.
Code-Apprentice