预取不适用于 ForeignKey 的 related_name? (结果为 n + 2 个查询)
Prefetch not working for ForeignKey's related_name? (Results in n + 2 queries)
# models.py
class Author(models.Model):
name = CharField()
class Book(models.Model):
title = CharField()
author = ForeignKey(Author, related_name="books")
# serializer.py
class BookSerializer(serializers.ModelSerializer):
class Meta:
model = Book
fields = ["id", "title"]
class AuthorSerializer(serializers.ModelSerializer):
books = serializers.SerializerMethodField()
class Meta:
model = Author
fields = ["id", "name", "books"]
def get_books(self, obj):
qs = obj.books
return BookSerializer(qs, many=True).data
# views.py
class AuthorListView(generics.ListAPIView):
queryset = Author.objects.all().prefetch_related("books")
serializer_class = AuthorSerializer
看起来相对简单,但我仍然收到 n + 2
个查询?
我希望只收到 2 个查询 - 一个针对所有作者,一个针对所有书籍?
如果我真的将视图的查询集简化为 Author.objects.all()
,我会得到 n + 1
个查询。
编辑
如果我设置一个 BookListView
而不是 queryset = Book.objects.all().select_related("author")
,它预取很好,结果页面只有 1 个查询。
啊,算了。我实际上是在我的 Serializer 方法中订购我的书,该方法添加了额外的查询:
def get_books(self, obj):
qs = obj.books.order_by(XXX)
return BookSerializer(qs, many=True).data
如果我删除那个排序,它确实只是两个查询。
# models.py
class Author(models.Model):
name = CharField()
class Book(models.Model):
title = CharField()
author = ForeignKey(Author, related_name="books")
# serializer.py
class BookSerializer(serializers.ModelSerializer):
class Meta:
model = Book
fields = ["id", "title"]
class AuthorSerializer(serializers.ModelSerializer):
books = serializers.SerializerMethodField()
class Meta:
model = Author
fields = ["id", "name", "books"]
def get_books(self, obj):
qs = obj.books
return BookSerializer(qs, many=True).data
# views.py
class AuthorListView(generics.ListAPIView):
queryset = Author.objects.all().prefetch_related("books")
serializer_class = AuthorSerializer
看起来相对简单,但我仍然收到 n + 2
个查询?
我希望只收到 2 个查询 - 一个针对所有作者,一个针对所有书籍?
如果我真的将视图的查询集简化为 Author.objects.all()
,我会得到 n + 1
个查询。
编辑
如果我设置一个 BookListView
而不是 queryset = Book.objects.all().select_related("author")
,它预取很好,结果页面只有 1 个查询。
啊,算了。我实际上是在我的 Serializer 方法中订购我的书,该方法添加了额外的查询:
def get_books(self, obj):
qs = obj.books.order_by(XXX)
return BookSerializer(qs, many=True).data
如果我删除那个排序,它确实只是两个查询。