Empresas
Empleos
  • Sobre nosotros
  • Soluciones
    • Publicación de vacantes
      Publica tu vacante y recibe candidatos calificados en 48h.
    • Evaluación de candidatos
      500+ pruebas técnicas y psicológicas, más anti-fraude.
    • Headhunting
      Búsqueda ejecutiva a la medida de principio a fin.
    • Nómina + EOR
      Dispersión de nómina y EOR en más de 15 países de LATAM.
  • Precios
  • Empleos

0

274
Vistas
Recuento inverso de ManytoManyField con una condición

Tengo un caso de uso en el que tengo que contar las ocurrencias de ManyToManyField, pero se está volviendo más complejo de lo que pensaba.

modelos.py :

 class Tag(models.Model): name = models.CharField(max_length=100, unique=True) class People(models.Model): tag = models.ManyToManyField(Tag, blank=True)

Aquí tengo que crear una lista de Tags y la cantidad de veces que aparecen en general, pero solo para aquellas People que tienen> 0 y <6 etiquetas. Algo como:

 tag1 - 265338 tag2 - 4649303 tag3 - 36636 ...

Así es como se me ocurrió el conteo inicialmente:

 q = People.objects.annotate(tag_count=Count('tag')).filter(tag_count__lte=6, tag_count__gt=0) for tag in Tag.objects.all(): cnt = q.filter(tag__name=tag.name).count() # doing something with the cnt

Pero luego me di cuenta de que esto puede ser ineficiente ya que probablemente estoy iterando a través del modelo People muchas veces (los registros en People son mucho más grandes que los de Tag).

Intuitivamente, creo que debería poder hacer una iteración del modelo Tag sin ninguna iteración del modelo People . Entonces se me ocurrió esto:

 for tag in Tag.objects.all(): cnt = tag.people_set.annotate(tag_count=Count('tag')).filter(tag_count__lte=6).count() # doing something with the cnt

Pero, en primer lugar, esto no está dando los resultados esperados. En segundo lugar, estoy pensando que esto se ha vuelto más complejo de lo que parecía ser, así que quizás esté complicando algo simple. Todos los oídos a cualquier consejo.

Actualización: obtuve queryset.query y ejecuté la consulta en la base de datos para depurarla. Por alguna razón, la columna tag_count en la combinación resultante muestra todos los 1. Parece que no puedo entender por qué.

over 4 years ago · Santiago Trujillo
1 Respuestas
Responde la pregunta

0

Se puede hacer usando la consulta de campo inversa ManyToMany.

También reduciría la sobrecarga y cambiaría la mayor parte de la sobrecarga de python al servidor de la base de datos.

 from some_app.models import Tag, People from django.db.models import F, Value, Count, CharField from django.db.models.functions import Concat # queryset: people with tags >0 and <6, ie 1 to 5 tags people_qualified = People.objects.annotate(tag_count=Count('tag'))\ .filter(tag_count__range=(1, 5)) # query tags used with above category of people, with count tag_usage = Tag.objects.filter(people__in=people_qualified)\ .annotate(tag=F('name'), count=Count('people'))\ .values('tag', 'count') # Result: <QuerySet [{'count': 3, 'tag': u'hello'}, {'count': 2, 'tag': u'world'}]> # similarily, if needed the string output tag_usage_list = Tag.objects.filter(people__in=people_qualified)\ .annotate(tags=Concat(F('name'), Value(' - '), Count('people'), output_field=CharField()))\ .values_list('tags', flat=True) # Result: <QuerySet [u'hello - 3', u'world - 2']>
over 4 years ago · Santiago Trujillo Denunciar
Responde la pregunta
Encuentra empleos remotos

¡Descubre la nueva forma de encontrar empleo!

Top de empleos
Top categorías de empleo
Empresas
Publicar vacante Precios Comercial
Legal
Términos y condiciones Política de privacidad
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomiéndame algunas ofertas
Necesito ayuda