title: How to get multiple related models with as few queries possible
body: <p>I am having some difficulty linking/obtaining data from 3 models all related to one another. I'm thinking i've either designed them incorrectly or I don't fully understand how to work with parental and many-to-many fields.</p>
  <p>There are 3 models (<em>full models shown at end of question</em>):</p>
  <ul>
  <li><code>ClubManager</code> Where club names are entered</li>
  <li><code>ClubTimetables</code> The timetable, relevant to the <code>ClubManager</code></li>
  <li><code>DaysOfTheWeek</code> Mon-Sun, used by <code>ClubTimetables</code></li>
  </ul>
  <p>For which I am trying to retrieve information from all of them: the name of the club, its timetable(s) and for each timetable the days of the week it's linked to. However, I can't seem to do it in a way that doesn't constantly hit the database.</p>
  <p>First thing I tried was to get <code>ClubManager</code> and <code>select_related</code> it's timetable but couldn't figure out how to preselect the <code>DaysOfTheWeek</code> it was connected with.</p>
  <p>The approach I am trying now is to instead get the <code>ClubTimetable</code> and use <code>select_related</code> and <code>prefetch_related</code> on both the models it's linked with, like so</p>
  <pre class="lang-py prettyprint-override"><code>timetable = ClubTimetables.objects.select_related('attached_to').prefetch_related('weekday')
  
  for t in timetable:
      print(t.attached_to.name)
  </code></pre>
  <p>This results in such a query</p>
  <pre class="lang-py prettyprint-override"><code>connection.queries
   
  [{'sql': 'SELECT &quot;club_clubtimetables&quot;.&quot;id&quot;, &quot;club_clubtimetables&quot;.&quot;sort_order&quot;, &quot;club_clubtimetables&quot;.&quot;address_line_1&quot;, &quot;club_clubtimetables&quot;.&quot;address_line_2&quot;, &quot;club_clubtimetables&quot;.&quot;address_city&quot;, &quot;club_clubtimetables&quot;.&quot;address_county&quot;, &quot;club_clubtimetables&quot;.&quot;address_country&quot;, &quot;club_clubtimetables&quot;.&quot;map_coord_lat&quot;, &quot;club_clubtimetables&quot;.&quot;map_coord_lon&quot;, &quot;club_clubtimetables&quot;.&quot;attached_to_id&quot;, &quot;club_clubtimetables&quot;.&quot;start_time&quot;, &quot;club_clubtimetables&quot;.&quot;end_time&quot;, &quot;club_clubmanager&quot;.&quot;id&quot;, &quot;club_clubmanager&quot;.&quot;name&quot; FROM &quot;club_clubtimetables&quot; INNER JOIN &quot;club_clubmanager&quot; ON (&quot;club_clubtimetables&quot;.&quot;attached_to_id&quot; = &quot;club_clubmanager&quot;.&quot;id&quot;) ORDER BY &quot;club_clubtimetables&quot;.&quot;sort_order&quot; ASC',
    'time': '0.020'},
   {'sql': 'SELECT (&quot;club_clubtimetables_weekday&quot;.&quot;clubtimetables_id&quot;) AS &quot;_prefetch_related_val_clubtimetables_id&quot;, &quot;core_daysoftheweek&quot;.&quot;id&quot;, &quot;core_daysoftheweek&quot;.&quot;weekday&quot; FROM &quot;core_daysoftheweek&quot; INNER JOIN &quot;club_clubtimetables_weekday&quot; ON (&quot;core_daysoftheweek&quot;.&quot;id&quot; = &quot;club_clubtimetables_weekday&quot;.&quot;daysoftheweek_id&quot;) WHERE &quot;club_clubtimetables_weekday&quot;.&quot;clubtimetables_id&quot; IN (1, 2)',
    'time': '0.002'}]
  </code></pre>
  <p>Which looks correct(?)</p>
  <p>But, trying to obtain the related weekdays hits the database each time.</p>
  <pre class="lang-py prettyprint-override"><code>for t in timetable:
      for training in t.weekday.values():
          print(training['weekday'])
  
  # Tuesday
  # Sunday
  
  In [14]: connection.queries
  Out[14]: 
  [{'sql': 'SELECT &quot;core_daysoftheweek&quot;.&quot;id&quot;, &quot;core_daysoftheweek&quot;.&quot;weekday&quot; FROM &quot;core_daysoftheweek&quot; INNER JOIN &quot;club_clubtimetables_weekday&quot; ON (&quot;core_daysoftheweek&quot;.&quot;id&quot; = &quot;club_clubtimetables_weekday&quot;.&quot;daysoftheweek_id&quot;) WHERE &quot;club_clubtimetables_weekday&quot;.&quot;clubtimetables_id&quot; = 1',
    'time': '0.001'},
   {'sql': 'SELECT &quot;core_daysoftheweek&quot;.&quot;id&quot;, &quot;core_daysoftheweek&quot;.&quot;weekday&quot; FROM &quot;core_daysoftheweek&quot; INNER JOIN &quot;club_clubtimetables_weekday&quot; ON (&quot;core_daysoftheweek&quot;.&quot;id&quot; = &quot;club_clubtimetables_weekday&quot;.&quot;daysoftheweek_id&quot;) WHERE &quot;club_clubtimetables_weekday&quot;.&quot;clubtimetables_id&quot; = 2',
    'time': '0.000'}]
  
  # ran again...
  
  for t in timetable:
      for training in t.weekday.values():
          print(training['weekday'])
  
  # Tuesday
  # Sunday
  
  In [16]: connection.queries
  Out[16]: 
  [{'sql': 'SELECT &quot;core_daysoftheweek&quot;.&quot;id&quot;, &quot;core_daysoftheweek&quot;.&quot;weekday&quot; FROM &quot;core_daysoftheweek&quot; INNER JOIN &quot;club_clubtimetables_weekday&quot; ON (&quot;core_daysoftheweek&quot;.&quot;id&quot; = &quot;club_clubtimetables_weekday&quot;.&quot;daysoftheweek_id&quot;) WHERE &quot;club_clubtimetables_weekday&quot;.&quot;clubtimetables_id&quot; = 1',
    'time': '0.001'},
   {'sql': 'SELECT &quot;core_daysoftheweek&quot;.&quot;id&quot;, &quot;core_daysoftheweek&quot;.&quot;weekday&quot; FROM &quot;core_daysoftheweek&quot; INNER JOIN &quot;club_clubtimetables_weekday&quot; ON (&quot;core_daysoftheweek&quot;.&quot;id&quot; = &quot;club_clubtimetables_weekday&quot;.&quot;daysoftheweek_id&quot;) WHERE &quot;club_clubtimetables_weekday&quot;.&quot;clubtimetables_id&quot; = 2',
    'time': '0.000'},
   {'sql': 'SELECT &quot;core_daysoftheweek&quot;.&quot;id&quot;, &quot;core_daysoftheweek&quot;.&quot;weekday&quot; FROM &quot;core_daysoftheweek&quot; INNER JOIN &quot;club_clubtimetables_weekday&quot; ON (&quot;core_daysoftheweek&quot;.&quot;id&quot; = &quot;club_clubtimetables_weekday&quot;.&quot;daysoftheweek_id&quot;) WHERE &quot;club_clubtimetables_weekday&quot;.&quot;clubtimetables_id&quot; = 1',
    'time': '0.001'},
   {'sql': 'SELECT &quot;core_daysoftheweek&quot;.&quot;id&quot;, &quot;core_daysoftheweek&quot;.&quot;weekday&quot; FROM &quot;core_daysoftheweek&quot; INNER JOIN &quot;club_clubtimetables_weekday&quot; ON (&quot;core_daysoftheweek&quot;.&quot;id&quot; = &quot;club_clubtimetables_weekday&quot;.&quot;daysoftheweek_id&quot;) WHERE &quot;club_clubtimetables_weekday&quot;.&quot;clubtimetables_id&quot; = 2',
    'time': '0.001'}]
  </code></pre>
  <p>Perhaps it is because I'm using <code>.values()</code>? But I don't know how else to obtain those values.</p>
  <p>My models currently look something like this</p>
  <pre class="lang-py prettyprint-override"><code># ClubManager
  
  @register_snippet
  class ClubManager(ClusterableModel):
  
      name = models.CharField('Club name',
                              max_length=255,
                              help_text='The name of the club.')
  
      panels = [
          FieldPanel('name'),
          InlinePanel('club_timetable', heading='Timetable Information')
      ]
  </code></pre>
  <pre class="lang-py prettyprint-override"><code># ClubTimetables
  
  class ClubTimetables(Orderable, AddressBase):
  
      attached_to = ParentalKey(
          'club.ClubManager', related_name='club_timetable')
  
      weekday = models.ManyToManyField(DaysOfTheWeek)
  
      start_time = models.TimeField()
      end_time = models.TimeField()
  
      panels = [ ... ] + AddressBase.panels
  </code></pre>
  <pre class="lang-py prettyprint-override"><code># DaysOfTheWeek
  
  class DaysOfTheWeek(models.Model):
  
      weekday = models.CharField(max_length=9)
  
      def __str__(self):
          return self.weekday
  </code></pre>
  <p>What can I do to fetch all relevant data from these models in one go without repeating db calls?<br />
  Or, if I designed these models incorrectly, in what way could build them to use it in the way intended?</p>