Search code examples
djangodatabasecachingmany-to-many

Django: Select related over nested foreign keys


I have:

class A(models.Model):
    pass
class AList(models.Model):
    list_of_a= models.ManyToManyField(A)
    random_statistical_info=models.CharField()
class B(models.Model):
    a_list = models.ForeignKey(AList)

I am defining AList like this, as my code is going to define functions that make more sense, when used with lists of A, and not A. ie, meta-data stuff, etc.

Now, my question is, How can I use select_related/prefetch_related so that I can save all the A instances as well as x in AList when I run a filter query over B?


Solution

  • The following will work:

    b_qs = B.objects.prefetch_related('a_list__list_of_a')
    

    Now

    for b in b_qs:
        x = b.a_list.list_of_a.all()
    

    will result in three db queries:

    Fetching table B, table AList, and table A using an INNER JOIN on the m2n table:

    1 SELECT app_b.*
      FROM app_b
    
    2 SELECT app_alist.*
      FROM app_alist 
      WHERE app_alist.id IN (1, 2, ...)  # fk values from 1
    
    3 SELECT (app_alista.alist_id) AS _prefetch_related_val_alist_id, 
      app_a.*
      INNER JOIN app_alista ON app_a.id = app_alista.a_id 
      WHERE app_alista.alist_id IN (1, 2, ... )  # pk values from 2