2011-05-25 4 views
1

Bonjour, Je suis en train de coder un site qui utilise des dons en tant qu'éléments multiples sur un projet. Je calcule le montant total des dons, mais cela ne semble pas fonctionner. Ai-je besoin d'une table intermédiaire entre les deux modèles?Agrégation Django dans le modèle

Je me demandais s'il y avait une meilleure façon de le faire avec 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 

Merci pour votre aide aimable!

+0

Vous devez écrire le code que vous avez déjà essayé. Cela nous donnerait une meilleure idée de ce que vous recherchez. –

+0

Un seul don sera-t-il versé à plusieurs projets? Sinon, vous ne voulez probablement pas beaucoup de champ. Vous pouvez placer un champ de clé étrangère dans Donation to Project à la place. –

+0

Bryce, merci pour votre réponse. J'essaie le code au moment où on se parle, sans résultat: S –

Répondre

3

je me débarrasser de la méthode progess et annoter simplement le queryset:

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

Vous pouvez même utiliser une coutume 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() 

Puis:

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

Ou vous pouvez même remplacer le jeu de requête par défaut afin que la progression soit toujours renvoyée:

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')) 

Puis:

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

Cette route serait le meilleur choix. –

+0

Oui, créer un manager est la meilleure option. –

+0

Mais de toute façon ça ne marche pas dans mon modèle: S –

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 

Je pense que cela vous donnera ce que vous voulez. Vous devrez jouer avec un peu, et laissez-moi savoir si vous avez des problèmes. Assurez-vous également que la version de Django prend en charge l'agrégation.

EDIT: Correction d'un problème où aucun n'était retourné.

+0

Cela semble être la solution ... mais je continue à obtenir "None" dans la valeur de retour –

+0

Y a-t-il des dons avec des montants liés à ce projet? –

+0

Oui, je teste le projet avec 2 dons (articles) ajouté –