web-dev-qa-db-fra.com

Obtenir un nombre d'objets dans un ensemble de requêtes dans django

Comment puis-je ajouter un champ pour le nombre d'objets dans une base de données. J'ai les modèles suivants:

class Item(models.Model):
    name = models.CharField()

class Contest(models.Model);
    name = models.CharField()

class Votes(models.Model):
    user = models.ForeignKey(User)
    item = models.ForeignKey(Item)
    contest = models.ForeignKey(Contest)
    comment = models.TextField()

Pour trouver les votes pour le concours A, j'utilise la requête suivante à mon avis

current_vote = Item.objects.filter(votes__contest=contestA)

Cela renvoie un ensemble de requêtes avec tous les votes individuellement, mais je veux obtenir le nombre de votes pour chaque élément, quelqu'un sait comment je peux le faire? Merci

46
thesteve

Pour obtenir le nombre de votes pour un élément spécifique, vous utiliseriez:

vote_count = Item.objects.filter(votes__contest=contestA).count()

Si vous vouliez une ventilation de la répartition des votes dans un concours particulier, je ferais quelque chose comme ceci:

contest = Contest.objects.get(pk=contest_id)
votes   = contest.votes_set.select_related()

vote_counts = {}

for vote in votes:
  if not vote_counts.has_key(vote.item.id):
    vote_counts[vote.item.id] = {
      'item': vote.item,
      'count': 0
    }

  vote_counts[vote.item.id]['count'] += 1

Cela va créer un dictionnaire qui mappe les éléments au nombre de votes. Ce n'est pas le seul moyen de le faire, mais c'est assez léger sur les hits de base de données, donc cela fonctionnera assez rapidement.

83
Gary Chambers

Une autre façon de procéder serait d'utiliser Agrégation . Vous devriez pouvoir obtenir un résultat similaire en utilisant une seule requête. Tel que cela:

Item.objects.values("contest").annotate(Count("id"))

Je n'ai pas testé cette requête spécifique, mais cela devrait produire un décompte des éléments pour chaque valeur dans les concours sous forme de dictionnaire.

10
salomonvh