Sethen
Sethen

Reputation: 11348

Django get foreign key objects

I am coming from .NET Core and I am curious if Django has anything similar to .NET Core's projections. For instance, I can describe a relationship in a .NET Core model and then later query for it. So, if Articles can have an Author I can do something like:

var articles = dbContext.Where(article.ID == id).Inclue(a => a.author);

What I would get back are articles that have their author attached.

Is there anything similar to this in Django? How can I load related data in Django that's described in the model?

Upvotes: 2

Views: 6220

Answers (2)

willeM_ Van Onsem
willeM_ Van Onsem

Reputation: 476537

Yes. The query you wrote is more or less equivalent to:

Article.objects.filter(id=some_id).prefetch_related('author')

or:

Article.objects.filter(id=some_id).select_related('author')

select_related versus prefetch_related

in case the number of Authors is limited, or more a one-to-one relation. In case you pull a large number of Articles, and several Articles map to the same Author, it is usually better to use prefetch_related: this will first look for the Author identifiers, perform a uniquness filter, and then fetch those into memory.

The same holds if multiple Authors write one article (so a one-to-many or many-to-many relation). Since that would mean that if we perform a JOIN at the database level, we repeat every article by the number of Authors who wrote that article, and we repeat every Author by the number of Articles they wrote. We usually want to avoid this "multiplicative" behavior for such sets. So in that case prefetch_related will have linear behavior: first fetching the relevant Articles, next fetching the relevant Authors.

Lazy loading of related objects

But you actually do not need to perform a prefetch_related for a single instance. In case you load an article, you can simply use some_article.author. If the corresponding Author instance is not yet loaded, Django will perform an additional query fetching the related Author instance.

So Django can load attributes that correspond to related objects in a lazy manner: it simply loads the Article if you fetch it in memory, and if you later need the Author, or the Journal, or the .editor of the Journal (which is for example an Author as well), Django will each time make a new query and load related object(s). In case you want however to process a list of Articles in batch, select_related and prefect_related are advisable, since they will result in a limited number of queries to fetch all related objects, instead of one query per related instance.

The lazy loading of related objects can be more efficient if one frequently has to fetch zero or at most a few related instances (for example because it depends on some attributes of the Article whether we are really interested in the Author after all).

Upvotes: 4

dfundako
dfundako

Reputation: 8314

Sounds like you are looking for select_related. This traverses FK relationships based on how they are created in your models.

Upvotes: 3

Related Questions