如何在 django(DRF)中检索对象列表(包括 ForeignKey 字段数据)而不显着增加数据库调用时间
Posted
技术标签:
【中文标题】如何在 django(DRF)中检索对象列表(包括 ForeignKey 字段数据)而不显着增加数据库调用时间【英文标题】:How to retrieve a list of objects (including ForeignKey Field data) in django (DRF) without significantly increasing DB call times 【发布时间】:2021-09-17 15:00:32 【问题描述】:我在一个 django DRF 项目中有三个模型:
class ModelA(models.Model):
name = ....
other fields...
class ModelB(models.Model):
name = ....
other fields...
class ModelC(models.Model):
name = ....
model_a = FKField(ModelA)
model_b = FKField(ModelB)
我为每个模型使用默认的 ModelViewSet 序列化程序。
在我的 react 前端,我正在显示一个包含 100 个 ModelC 对象的表格。请求耗时 300 毫秒。问题是,我不想在我的表中只显示 modelA 和 ModelB 的 pk id,而是想显示它们的名称。当我使用视图集的 list() 方法(检索所有 modelc 对象)时,我尝试了以下方法来获取该数据,但它显着增加了调用时间:
-
序列化 ModelCSerializer 中的字段
class ModelCSerializer(serializers.ModelSerializer):
model_a = ModelASerializer(read_only=True)
model_b = ModelBSerializer(read_only=True)
class Meta:
model = ModelC
fields = '__all__'
-
创建新的序列化程序以仅返回 FK 对象的名称
class ModelCSerializer(serializers.ModelSerializer):
model_a = ModelANameSerializer(read_only=True) (serializer only returns id and name)
model_b = ModelBNameSerializer(read_only=True) (serializer only returns id and name)
class Meta:
model = ModelC
fields = '__all__'
-
字符串相关字段
class ModelCSerializer(serializers.ModelSerializer):
model_a = serializer.StringRelatedField()
model_b = serializer.StringRelatedField()
class Meta:
model = ModelC
fields = '__all__'
每种方式都返回我需要的数据(除了数字 3 需要更多工作来获取 FKobject 的 id),但现在我的表请求需要 5.5 秒。有没有办法在不显着增加通话时间的情况下做到这一点?我猜这是因为数据库为我检索的每个对象查找 3 个对象。
此外,我无法将 ModelA 和 ModelB 的 primary_key 设为名称字段,因为它们不是唯一的。
谢谢
感谢下面的 bdbd,为我的示例编辑答案:
class ModelCViewSet(viewsets.ModelViewSet):
queryset = ModelC.objects.select_related('model_a', 'model_b').all()
# ...
【问题讨论】:
查看select_related
以优化您的查询:https://docs.djangoproject.com/en/3.2/ref/models/querysets/#select-related
可以分享您的查询集或您如何使用序列化程序?
我在 ModelCViewSet 中的查询集只是 ModelC.objects.all()。我会试试 select_related 让你知道,听起来很有希望
【参考方案1】:
您可以为此使用select_related 来优化您的查询,并确保您的ModelC
中的每个对象都不会造成额外的数据库命中
【讨论】:
以上是关于如何在 django(DRF)中检索对象列表(包括 ForeignKey 字段数据)而不显着增加数据库调用时间的主要内容,如果未能解决你的问题,请参考以下文章
在 DRF 中确定 IsAuthenticated 使用 DRF-JWT 检索使用 Postman 测试的列表
Django - DRF 删除/检索/补丁返回 404 详细信息:“未找到”