Search code examples
djangomany-to-manyprefetch

Django - One query to get M2M objects


Entry model and Reference have M2M relationship.

class Entry(models.Model):
  description = models.TextField(blank=True, null=True)
  references = models.ManyToManyField(Reference, blank=True)

class Reference(models.Model):
  name = models.CharField(max_length=1000, blank=True, null=True)
  title = models.CharField(max_length=1000, blank=True, null=True)

I need to iterate over the entries and get a field from Entry. Also for each entry, I need to iterate over its references, and get data from each reference.

prefetch_related is not caching all the reference data. For each entry, I am hitting the db again when I call entry.references.all(), and the performance is terrible (I have 100k entries, and 500k references).

How can I get all the data in one database call?

qs = Entry.objects.prefetch_related('references').all()
for entry in qs:
   # do something with entry
   for ref in entry.references.all():
     # do something with ref

Solution

  • I missed that Reference has a foreign key to Source. When I include Source model in prefetch_related, performance went from 8 minutes to 80 seconds (which is acceptable).

    qs = CVEEntry.objects.prefetch_related('references', 'references__source').all()