Home > OS >  How to use prefetch_related on two M2M values?
How to use prefetch_related on two M2M values?

Time:07-16

I want to prefetch_related to two level of M2M values,

Here is my models.py

class A(models.Model):
    name = models.CharField(max_length=40)
    b = models.ManyToManyField('B')

class B(models.Model):
    name = models.CharField(max_length=40)
    c = models.ManyToManyField('C')

class C(models.Model):
    name = models.CharField(max_length=40)
    d = models.ManyToManyField('D')

And my ORM is

a_obj = A.objects.all().prefetch_related('a__b__c')

And I am trying to access the values like below,

Method A:

for each_obj in a_obj:
    print(each_obj.a__b__c)

Method B:

for each_obj in a_obj:
    print(each_obj.a.all())

Method A throws an error saying No such value a__b__b for A found Method B doesn't throw any error, but the number of queries increases to the length of a_obj.

Is there a way to access a__b__c in a single query?

CodePudding user response:

You load both the related B and C models with .prefetch_related(…) [Django-doc]:

a_objs = A.objects.prefetch_related('b__c')

But here .prefetch_related(…) does not change how the items look, it simply loads items. You thus can access these with:

for a in a_objs:
    for b in a.b.all():
        for c in b.c.all():
            print(f'{a} {b} {c}')

You this still access the items in the same way, but here Django will already load the objects in advance to prevent extra queries.

  • Related