使用 django-auto-prefetching 优化 Django REST Framework 性能

530 阅读2分钟

django-auto-prefetching 是一个库,它通过在使用django-rest-framework 时使用prefetch_relatedselect_related从数据库中获取正确的对象来自动优化您的端点。

Django REST 框架和 n+1 问题

Django REST 框架(DRF)是一个用于快速构建强大的 REST API 的框架。然而,当获取具有嵌套关系的模型时,我们会遇到性能问题。DRF 变得缓慢。

这不是由于 DRF 本身,而是由于 n+1 问题。当我们有一个模型时,比如说Article有一个关系Author,我们想要获取所有文章与它们相应的作者。这意味着我们可能会进行大量查询,因为 DRF 首先获取所有文章,然后为每个文章分别获取它们的作者。这意味着如果有 20 篇文章,我们最终将对作者进行 20 个单独的数据库调用。

Django 有一个内置的解决方案来解决这个问题,select_related和prefetch_related,它告诉 ORM 你将需要哪些相关的对象。这意味着我们可以只做一次数据库调用,而不是进行一堆数据库调用。

然而,这有两个问题

  • 很难准确跟踪您最终将遍历哪些关系,
  • 手动编写select_related和prefetch_related调用很耗时,更不用说在其他地方的代码更改时保持更新。

django-auto-prefetching

这个库的目标是毫不费力地、尽可能轻松地确保您不会因 n+1 问题而遭受性能问题。我们从 DRF 序列化程序的自动预取开始。

安装

pip install django-auto-prefetching

用法

Django-auto-prefetching 有一个 AutoPrefetchViewSetMixin,它查看任何给定序列化器使用的字段,并自动计算正确的select_related和prefetch_related调用。

这意味着一行代码就是您的许多视图将需要的所有优化!

class ChefViewSet(AutoPrefetchViewSetMixin, ModelViewSet):
    serializer_class = ArticleSerializer
    queryset = Article.objects.all()

手动调用

在AutoPrefetchViewSetMixin不能看到如SerializerMethodField中正在被访问的对象。如果您使用其中的对象,则可能需要进行一些额外的预取。如果你这样做并覆盖get_queryset,你将不得不手动调用prefetch,因为这个mixin的代码是无法达到的。

import django_auto_prefetching

class BaseModelViewSet(django_auto_prefetching.AutoPrefetchViewSetMixin, ModelViewSet):
    serializer_class = YourModelSerializer

    def get_queryset(self):
        queryset = YourModel.objects.all()
        queryset = queryset.select_related('my_extra_field')
        return django_auto_prefetching.prefetch(queryset, self.serializer_class)

原文:itnext.io/optimizing-…

扫码_搜索联合传播样式-标准色版.png