请考虑以下模型:
class Author(models.Model):
name = models.CharField(max_length=100)
class Book(models.Model):
author = models.ForeignKey(Author, related_name="books", on_delete=models.CASCADE)
title = models.CharField(max_length=100)
created_at = models.DateTimeField(auto_now_add=True)
和以下代码:
queryset = Author.objects.all()
for author in queryset:
print(author.name)
print(author.books.latest("created_at").title)
如上所述,将导致N+1个查询.
我试着通过预取books
来修复它,如下所示:
queryset = Author.objects.prefetch_related('books')
然而,这并不能解决N+1问题.
我认为原因是预取的结果是SELECT * FROM book WHERE author_id IN (1,2,...)
,这与调用.Latest()所执行的查询不同,即SELECT * FROM book WHERE author_id = 1 ORDER BY created_at DESC LIMIT 1
.预取操作执行IN
,.Latest()执行=
操作.
我还try 了以下几种方法,但都没有成功:
queryset = Author.objects.prefetch_related(Prefetch('books', queryset=Book.objects.order_by("-created_at")))
在使用.Latest()时,为了避免N+1个 Select ,预取应该是什么样子?