Агрегация Джанго в модели - PullRequest
1 голос
/ 26 мая 2011

Привет, я пишу сайт, который использует пожертвования в качестве нескольких элементов в проекте.Я подсчитываю общую сумму пожертвований, но, похоже, это не сработает.Нужна ли промежуточная таблица между двумя моделями?

Мне было интересно, есть ли лучший способ сделать это с помощью 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 ]

3 голосов
/ 26 мая 2011

Я бы избавился от метода 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 голос
/ 26 мая 2011
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 поддерживает агрегацию.

РЕДАКТИРОВАТЬ: Исправлена ​​проблема, когда ни один не был возвращен.

...