优化 DRF 序列化

时间:2021-06-01 15:00:53

标签: sql python-3.x django django-rest-framework

我面临一个问题,我必须优化 ORM 对象的序列化。我有一个对象说 Foo,我有一个巨大的序列化程序。我提到了很多领域,比如

class FooSerializer(ModelSerializer):
    bar = serializers.StringRelatedField(source="bar")
    apple = serializers.StringRelatedField(source="bar.food")
    cat = serializers.StringRelatedField(source="bar.animals.pet")
    ball = serializers.StringRelatedField(source="bar.toy")
    # a lot of other complex fields related with Foo
    # direct-indirect, 1-1 or 1-M relations
    class Meta:
        model = Foo
        fields = ['bar', 'apple', 'cat', 'ball', ....]

现在,这导致序列化需要大量时间。我添加了日志记录并看到许多 SQL 查询被执行。重复这些查询很多。根据我从文档中的理解,即使 Django QuerySet 被延迟执行,DRF 中的序列化也会查询每个字段以进行填充。请详细说明如何在较低级别填充序列化字段,这对我有更多帮助。

我想在这里实现的是尽可能少的查询。在上面的示例中,要获取 bar.foodbar.toy,我只想执行一个查询,该查询将获取 bar 对象,并且我可以访问 foodtoy对象。

我能想到的一种可能的解决方案是评估所有相关对象并在上下文中传递它们。也就是说,评估 bar 对象并将其作为上下文发送。然后我的 apple 字段将在 self.context['bar'].food 中填充为 SerializerMethodField。你能提出更好的方法吗?可能是批处理?

假设: 序列化数据很热,我们无法缓存它。

编辑: 当前正在执行的 SQL 查询对于每个序列化都是两位数的。

编辑(Daneil 要求的查询)

SELECT `app_foo`.`id`, `app_foo`.`field_1`, (many app_foo fields),
`app_foo`.`created_at`, `app_foo`.`updated_at` FROM `app_foo` INNER JOIN
`app_bar` ON `app_foo`.`id` = `app_bar`.`id` WHERE `app_foo`.`id` = 12; args(12,)

1 个答案:

答案 0 :(得分:1)

亲爱的 NIkhil 请尝试使用预取选择和选择相关

主 QuerySet 的结果缓存和所有指定的相关对象将被完全加载到内存中。这改变了 QuerySets 的典型行为,它通常会尽量避免在需要之前将所有对象加载到内存中,即使在数据库中执行了查询之后也是如此。 更多详情here

相关问题