Reputation: 739
In Django's documentation, there is the following example.
>>> b = Blog.objects.get(pk=1)
# Update all the headlines belonging to this Blog.
>>> Entry.objects.select_related().filter(blog=b).update(headline='Everything is the same')
And the example is based on the following definitions of models.
from django.db import models
class Blog(models.Model):
name = models.CharField(max_length=100)
tagline = models.TextField()
def __str__(self):
return self.name
class Author(models.Model):
name = models.CharField(max_length=200)
email = models.EmailField()
def __str__(self):
return self.name
class Entry(models.Model):
blog = models.ForeignKey(Blog, on_delete=models.CASCADE)
headline = models.CharField(max_length=255)
body_text = models.TextField()
pub_date = models.DateField()
mod_date = models.DateField()
authors = models.ManyToManyField(Author)
number_of_comments = models.IntegerField()
number_of_pingbacks = models.IntegerField()
rating = models.IntegerField()
def __str__(self):
return self.headline
What is the benefit of having select_related()
in the line of Entry.objects.select_related().filter(blog=b).update(headline='Everything is the same')
?
I don't see any benefit of having select_related()
in the update statement. In fact, I think Entry.objects.filter(blog=b).update(headline='Everything is the same')
has a better performance for it doesn't perform an unneeded inner join and doesn't populate the unneeded Blog objects.
What do you think?
Upvotes: 2
Views: 45
Reputation: 477230
I don't see any benefit of having
select_related()
in the update statement.
Indeed. .select_related(…)
[Django-doc] has nothing to do with .filter(…)
[Django-doc]. It only means that when you retrieve data, it will already retrieve related objects, and wrap these columns in objects that are accessed through the ForeignKey
. It thus is a mechanism to avoid N+1 problems.
But for filtering, annotating, etc. Django will construct a query that makes a join with the necessary tables when used. Here one thus can omit the .select_related(…)
. This will normally be ignored by the Django ORM, since an UPDATE
on a query with JOIN
s will normally raise exceptions at the database level, since then it is no longer clear how to update this.
Likely this is a copy-paste from the One-to-many relationships sections of the documentation, where we see:
>>> e = Entry.objects.select_related().get(id=2)
Update: I created a ticket for this, and it was fixed in the source code [GitHub]
Upvotes: 1