django select_related for multiple foreign keys
Asked Answered
I

4

18

How does select_related work with a model which has multiple foreign keys? Does it just choose the first one?

class Model: fkey1, fkey2, fkey3...

The documentation doesn't say anything about this, at least not in where the method is specified.

NOTE: Maybe I'm the only one who will get confused. I guess select_related is just a performance booster (I can see that) but I had the wrong idea that it was something else.

Illtimed answered 17/1, 2013 at 18:12 Comment(0)
C
17

You can use select_related in a chain as following

Comment.objects.select_related('user').select_related('article').all()
Cataldo answered 24/12, 2015 at 4:9 Comment(2)
Just to be clear, user and article are both ForeignKey fields on Comment. The above is the equivalent of Comment.objects.select_related('user', 'article').all(). (Context: I'm researching whether you can select_related() across multiple relationships. The above does not do that.)Izanami
I used this code with django 1.4: related_fields = 'user, article, user__profile' Comment.objects.select_related(related_fields) However, it doesn't work in django 1.9, 'cause django thinks it's a single field which does NOT exist. When i convert related_fields to a list like this related_fields = ['user', 'article', 'user__profile'] it still complains that it can not apply split(',') to a list (which is obviously not a string). Is this a bug ?Coroneted
D
15

If your model has multiple foreign keys you can:

  • Call .select_related(), that will “follow” all non-null foreign-key relationships
  • Call .select_related('foreign_key1', 'foreign_key2', ...), that will “follow” only the foreign-key provided as arguments.

Note that "to follow a FK relationship" means selecting additional related-object data when the query is executed (by performing a SQL join). This will make the main query heavier but can be used to avoid N + 1 queries problem.

According to select_related documentation, the first method (without arguments) is not recommended as "it is likely to make the underlying query more complex, and return more data, than is actually needed."


If your model has "nested" foreign keys with other models (i.e. Book <>-- Author <>-- Hometown) you can also use select_related as follow:

  • Call Book.select_related('author__hometown'), that will “follow” the author's foreign-key (in Book model) and the hometown's foreign-key (in Author model).

If your model has many-to-many or many-to-one relations you would like to retrieve from the database, you should take a look at prefetch_related.

Daube answered 10/11, 2020 at 20:40 Comment(0)
F
7

On the contrary, the documentation is very clear on the matter. It says that by default all ForeignKeys are followed, but you can give the method a list of fields and it will only follow those relationships.

Fantastically answered 17/1, 2013 at 18:25 Comment(0)
M
2

You can pass foreign keys and even nested foreign keys to the select_related method eg select_related('book__author', 'publisher',) you can add as many foreign keys as you want, if you call select_related() without any argument then it will follow all the foreign key relationship which is not recommended at all because you'll be complicating the query by fetching data you don't need. Finally, from Django documentation "Chaining select_related calls works in a similar way to other methods - that is that select_related('foo', 'bar') is equivalent to select_related('foo').select_related('bar')

Melar answered 24/6, 2022 at 12:57 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.