When the database has foreign keys, using select_related() and prefetch_related() can reduce the number of database requests and improve performance
https://docs.djangoproject.com/en/3.2/ref/models/querysets/#select-related
https://developpaper.com/djangos-select_related-and-prefetch_related-functions-to-optimize-queryset-queries/
Join Tables without related
you can foreign key and one-to-one values eg: article.author.name
but you will hit the DB every time when accessing related models
artciles = Article.objects.all()
e = Entry.objects.get(id=5) # Hits the database.
b = e.blog # Hits the database again to get the related Blog object.
Select_related()
an optional performance booster
avoid hitting the DB when accessing related models
is limited to single-valued relationships
foreign key and one-to-one.
Artciles = Article.objects.select_related('reporter')
e = Entry.objects.select_related('blog').get(id=5)
Hits the database.
b = e.blog
Doesn't hit the database, because e.blog has been prepopulated, in the previous query.
Join in join
b = Book.objects.select_related('author__hometown').get(id=4)
p = b.author # Doesn't hit the database.
c = p.hometown # Doesn't hit the database.
Many foreign keys
Comment.objects.select_related('user', 'article').all()
Or
Comment.objects.select_related('user').select_related('article').all()
With Filter
Entry.objects.filter(pub_date__gt=timezone.now()).select_related('blog')
Or
Entry.objects.select_related('blog').filter(pub_date__gt=timezone.now())
Avoid redundent no need for 'pizzas' because it's included in 'pizzas__toppings'
select_related('pizzas__toppings', 'pizzas')
Clear the list of related fields added by past calls of select_related on a QuerySet
without_relations = queryset.select_related(None)
Prefetch_related()
an optional performance booster
avoid hitting the DB when accessing related models
does a separate lookup for each relationship
prefetch many-to-many and many-to-one objects
pizzas = Pizza.objects.all().prefetch_related('toppings')
Avoid redundent no need for 'pizzas' because it's included in 'pizzas__toppings'
prefetch_related('pizzas__toppings', 'pizzas')