模型中的Django聚合

时间:2011-05-25 20:28:20

标签: django aggregation

您好我正在编写一个将捐款用作项目中多个项目的网站。 我正在计算捐款总额,但似乎没有用。我需要两个模型之间的中间表吗?

我想知道是否有更好的方法来使用Django Aggregation。

class Donation(models.Model):
    user = models.ForeignKey(User)
    amount= models.DecimalField(max_digits=12, decimal_places=2)

    def __unicode__(self):
        return self.user

class Project(models.Model):
    name = models.CharField(max_length=200)
    donations=models.ManyToManyField(Donation, null=True, blank=True)

    def __unicode__(self):
        return self.name

    def progress(self):
        donations = self.donations.all()
        total_donations = 0
        for item in donations:
            total_donations += item.amount
        return total_donations

感谢您的帮助!

2 个答案:

答案 0 :(得分:3)

我将摆脱progess方法并简单地注释查询集:

from django.db.models import Sum
Project.objects.annotate(progress=Sum('donations__amount'))

您甚至可以使用自定义Manager

from django.db.models import Sum

class ProjectManager(models.Manager):
    def all_with_progress(self):
        return self.get_query_set().annotate(progress=Sum('donations__amount'))

class Project(models.Model)
    ...
    objects = ProjectManager()

然后:

>>> projects = Project.objects.all_with_progress()
>>> projects[0].progress
700

或者您甚至可以覆盖默认查询集,以便始终返回进度:

class ProjectManager(models.Manager):
    def get_query_set(self, *args, **kwargs):
        qs = super(ProjectManager, self).get_query_set(*args, **kwargs)
        return qs.annotate(progress=Sum('donations__amount'))

然后:

>>> projects = Project.objects.all()
>>> projects[0].progress
700

答案 1 :(得分:1)

def progress(self):
    from django.db.models import Sum
    amount = self.donations.exclude(amount=None).aggregate(progress=Sum('amount'))['progress']
    if amount:
        return amount
    return 0

我认为那会给你你想要的东西。你必须玩一下,如果你有任何问题,请告诉我。另外,请确保您的Django版本支持聚合。

编辑:修复了没有返回任何问题的问题。