steve
¿Cómo puedo agregar un campo para el recuento de objetos en una base de datos? Tengo los siguientes modelos:
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()
Para encontrar los votos para contestA estoy usando la siguiente consulta en mi opinión
current_vote = Item.objects.filter(votes__contest=contestA)
Esto devuelve un conjunto de consultas con todos los votos individualmente, pero quiero obtener el recuento de votos para cada elemento, ¿alguien sabe cómo puedo hacerlo? Gracias
Para obtener el número de votos para un elemento específico, usaría:
vote_count = Item.objects.filter(votes__contest=contestA).count()
Si quisiera un desglose de la distribución de votos en una contienda en particular, haría algo como lo siguiente:
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
Esto creará un diccionario que asigna elementos a la cantidad de votos. No es la única forma de hacer esto, pero es bastante ligero en los resultados de la base de datos, por lo que se ejecutará con bastante rapidez.
-
para cualquier persona interesada –
has_key
fue eliminado en Python 3: puede actualizarlo para usar elin
operador en su lugar. Ejemplo:.if vote.item.id not in vote_counts: vote_counts[vote.item.id] = { 'item': vote.item, 'count': 0 }
– RealScatman
6 de mayo a las 15:43
salomonvh
Otra forma de hacerlo sería usando Agregación. Debería poder lograr un resultado similar utilizando una sola consulta. Como esto:
from django.db.models import Count
Item.objects.values("contest").annotate(Count("id"))
No probé esta consulta específica, pero debería generar un recuento de los elementos para cada valor en los concursos como un diccionario.
-
Esto todavía es confuso para mí. Si anota en un conjunto de consultas, está contando la cantidad de ID que pertenecen a cada objeto, que obviamente es 1. Entonces, ¿cómo es eso útil?
– AlxVallejo
14 de junio de 2018 a las 17:08
-
Si, si estuvieras contando
contest
en el modelo Contest ese sería el caso. Sin embargo, en este caso estamos agregando enItem
que tienen concursos únicos.– salomonvh
18 de junio de 2018 a las 8:25
-
¿Qué sucede si el recuento de dos objetos es el mismo y luego tenemos que clasificarlos en función de alguna otra condición? Entonces, ¿cómo hacer eso?
– Tarún
6 sep 2018 a las 20:24
-
@Tarun puede agregar valores en la anotación, solo asegúrese de no intentar agregar elementos que se agreguen durante la anotación. Dado que devuelve un conjunto de consultas, se siguen aplicando todas las funciones de ordenación habituales.
.order_by('some_value')
.– salomonvh
7 sep 2018 a las 17:16
Use un nombre relacionado para contar los votos para un concurso específico
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, related_name="contest_votes")
comment = models.TextField()
>>> comments = Contest.objects.get(id=contest_id).contest_votes.count()
Puedes usar largo() Llegar el conteo de votos de contestA:
current_vote = len(Item.objects.filter(votes__contest=contestA))