2014-06-24 5 views
2

Peut-être que c'est une question très débutant, mais je suis coincé dans ce point. Je ne sais pas si le problème est le modèle ou je ne comprends pas très bien les agrégations et les annotations.scores moyens Django avec par

J'ai un modèle comme celui-ci:

class User(models.Model): 
    collection = models.ManyToManyField(Book, through='BookCollection') 

class Book(models.Model): 
    name   = models.CharField(max_length=200) 

class BookCollection(models.Model): 
    user   = models.ForeignKey(User) 
    book   = models.ForeignKey(Book) 
    score  = models.IntegerField(default=0) 

Je veux obtenir la moyenne des scores pour tous les livres et tous les utilisateurs, sauf que ceux qui a un score par défaut égal à 0 (cette valeur représente que la l'utilisateur a le livre dans la collection, mais il n'a pas été évalué). Je suis en train d'utiliser une annotation comme ceci:

Book.objects.exclude(collection__score=0).annotate(avg=Avg('collection__score')) 

mais s'il y a un livre évalué avec 0 et 3, par exemple, les deux entrées sont exclues.

Est-il possible de dire à Avg() qu'il ne devrait prendre en compte que les valeurs supérieures à 0?

Merci d'avance.

Répondre

1

Il n'y a aucun moyen de le faire dans l'ORM Django sans SQL brut.

Un meilleur modèle consisterait à autoriser les valeurs nulles dans votre champ score. Les valeurs NULL sont ignorées dans Avg():

class BookCollection(models.Model): 
    ... 
    score = models.IntegerField(null=True, blank=True, default=None) 

None est généralement la meilleure façon de décrire le manque d'une entrée dans un champ. Ceci évite la confusion, par ex. dans les calculs tels que le calcul de la moyenne.

+0

Merci beaucoup, je savais que je pouvais améliorer mon modèle. Ça marche! – KiKo