I figured the following query:
context['user_artists'] = Artist.objects.filter(users=current_user).all()
Coupled with the following usage in templates:
{% if user_artists %}
...
{% for artist in user_artists %}
....
<p class="small">last release: {{ artist.release_groups.last.title }}</p>
<p class="small">date: {{ artist.release_groups.last.release_date }}</p>
Was hitting the database 3 times for every artist in the query. I know this can be brought down to 2 by simple saving .last
in the template, but that still isn't fast enough.
I know I can use prefetch_related
like so:
Artist.objects.filter(users=current_user).prefetch_related(`release_groups`).all()
And I also need eliminate he usage of .last
since it implies another query. I can probably use the template engine's slice
method to get the last element. But then I have to order the related relationship: meaning, I need release_group
ordered by its own release_date
before I access them in the template. This must not affect the order of the artist objects.
How can this be done?
You can use Prefetch
:
Artist.objects.prefetch_related(Prefetch('release_groups', queryset=ReleaseGroup.objects.order_by('release_date')))
To avoid collision with the name, you can set to_attr
to a different name:
Artist.objects.prefetch_related(Prefetch('release_groups', queryset=ReleaseGroup.objects.order_by('release_date'), to_attr='rgs')).all()
You can then access each cached release group in the template like so:
artist.rgs.0.title