Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django prefetch_related from foreignkey with manytomanyfield not working

For example, in Django 1.8:

class A(models.Model):
    x = models.BooleanField(default=True)

class B(models.Model):
    y = models.ManyToManyField(A)

class C(models.Model):
    z = models.ForeignKey(A)

In this scenario, C.objects.all().prefetch_related('z__b_set') doesn't work.

Is there a way to prefetch the information I need for c[0].z.b_set.all() to work without an extra query?

like image 996
Sem Avatar asked Jan 07 '23 21:01

Sem


2 Answers

You can use select_related to follow the first part of the relationship (C.z's ForeignKey) in one batch:

C.objects.all().select_related('z').prefetch_related('z__b_set')

The prefetch_related part, however, will be done in at least two queries, as stated in the docs:

prefetch_related, on the other hand, does a separate lookup for each relationship, and does the ‘joining’ in Python. This allows it to prefetch many-to-many and many-to-one objects, which cannot be done using select_related, in addition to the foreign key and one-to-one relationships that are supported by select_related. It also supports prefetching of GenericRelation and GenericForeignKey.

like image 196
301_Moved_Permanently Avatar answered Jan 16 '23 21:01

301_Moved_Permanently


You should explicitly set the related_name in B and migrate:

class B(models.Model):
    y = models.ManyToManyField(A, related_name="bs")
like image 29
nima Avatar answered Jan 16 '23 22:01

nima