gpt4 book ai didi

django - 我可以使用 prefetch_related 来缓存过滤的查询集吗?

转载 作者:行者123 更新时间:2023-12-05 06:31:12 24 4
gpt4 key购买 nike

我正在使用 DRF 序列化一些相关模型。在我下面的玩具示例中,假设每个作者都可以拥有一百万本书。显然对所有“好”书进行数据库查询,然后对所有“坏”书进行另一个数据库查询是低效的。

这篇文章 [ http://ses4j.github.io/2015/11/23/optimizing-slow-django-rest-framework-performance/]提供了一些关于 prefetch_related 的建议。但我发现这仅在我随后调用 .books.all() 而不是 .books.filter() 时有所帮助,如下面的属性所示。

在 Django 中是否有任何自动方式来缓存书籍查询集并且没有有后续过滤器再次访问数据库?

这是一些代码:

模型.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")

序列化程序.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

谢谢。


编辑:

使用预取:

@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

这仍然为调用 filter 提供了额外的数据库命中率。

最佳答案

您可以在 View 级别进行预取,并使用带有 to_attr 参数的 Prefetch,而不是在模型的属性中执行此操作,这将分别为每个作者进行评估:

class AuthorViewSet(viewsets.ReadOnlyModelViewSet):
serializer = AuthorSerializer

def get_queryset(self):
queryset = Author.objects.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

关于django - 我可以使用 prefetch_related 来缓存过滤的查询集吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51875632/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com