I have a very simple datamodel with a one to many relationship between video and comments
class Video(models.Model):
url = models.URLField(unique=True)
.....
class Comment(models.Model):
title = models.CharField(max_length=128)
video = models.ForeignKey('Video')
.....
I want to query for videos and grab the whole object graph (videos with all the comments). Looking at the sql, I see it does two selects, one for the Videos and one for the Comments. How do I avoid that? I want to do a join and grab everything at once.
Is it possible to do this with django?
N+1 is a very common data-access pattern problem where a query is executed for every result of a previous query. If the definition looks cryptic, let's understand this problem with an example.
The N+1 query problem happens when the data access framework executed N additional SQL statements to fetch the same data that could have been retrieved when executing the primary SQL query. The larger the value of N, the more queries will be executed, the larger the performance impact.
The exclude() method from the QuerySet class returns all objects that do not match the given keyword arguments. So whatever data matches the parameter that is passed into the exclude() method will be excluded from the returned QuerySet.
The values_list() method allows you to return only the columns that you specify.
For ForeignKey, you can use selected_related():
Comment.objects.select_related('video').all()
It will generate one query only, gathering coments for you as well as videos.
For something more complex (such as M2M), you need an external app such as unjoinify to make optimizations but it uses SQL queries to then put them back in objects.
If you are unconfortable with this (I am), you have some alternatives:
select_related
that works with M2M and reverse relations.If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With