Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

273
Views
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 answers
Answer question

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 Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!