【发布时间】:2019-01-23 07:55:31
【问题描述】:
我正在使用 DRF 序列化一些相关模型。在下面我的玩具示例中,假设每个作者可以拥有一百万本书。显然,对所有“好”书进行数据库查询,然后对所有“坏”书进行另一个数据库查询效率低下。
这篇文章 [http://ses4j.github.io/2015/11/23/optimizing-slow-django-rest-framework-performance/] 提供了一些关于 prefetch_related 的建议。但我发现这仅在我随后调用.books.all() 而不是.books.filter() 时才有帮助,如下面的属性中发生的那样。
在 Django 中是否有任何 自动 方法来缓存书籍查询集,并且 没有 有后续过滤器再次访问数据库?
这里有一些代码:
models.py:
class Author(models.Model):
name = models.CharField(max_length=100)
@property
def good_books(self):
return self.books.filter(is_good=True)
@property
def bad_books(self):
return self.books.filter(is_good=False)
class Book(models.Model):
title = models.CharField(max_length=100)
is_good = models.BooleanField(default=False)
author = models.ForeignKey(Author, related_name="books")
serializers.py:
class BookSerializer(serializers.ModelSerializer):
class Meta:
model = Book
fields = ("title",)
class AuthorSerializer(serializers.ModelSerializer):
class Meta:
model = Author
fields = ("name", "good_books", "bad_books",)
good_books = BookSerializer(many=True, read_only=True, source="good_books")
bad_books = BookSerializer(many=True, read_only=True, source="bad_books")
@staticmethod
def setup_eager_loading(queryset):
queryset = queryset.prefetch_related("books")
return queryset
views.py:
class AuthorViewSet(viewsets.ReadOnlyModelViewSet):
serializer = AuthorSerializer
def get_queryset(self):
queryset = Author.objects.all()
queryset = self.get_serializer_class().setup_eager_loading(queryset)
return queryset
谢谢。
编辑:
使用Prefetch:
@staticmethod
def setup_eager_loading(queryset):
queryset = queryset.prefetch_related(
Prefetch("books", queryset=Book.objects.filter(is_good=True), to_attr="good_books"),
Prefetch("books", queryset=Book.objects.filter(is_good=False), to_attr="bad_books"),
)
return queryset
这仍然给我额外的 db hits 以调用filter。
【问题讨论】:
-
是的,您可以使用
Prefetch对象:docs.djangoproject.com/en/2.1/ref/models/querysets/… -
我试过了,但似乎没有帮助。我将编辑代码给你看。
标签: django django-rest-framework django-queryset