gpt4 book ai didi

mysql - Django ORM - 相关模型的 MySQL 查询计数优化

转载 作者:行者123 更新时间:2023-11-30 21:22:03 25 4
gpt4 key购买 nike

我有两个相关模型,如下所示:

class Enterprise(models.Model):
id = models.AutoField(primary_key=True)
subsystem_id = models.IntegerField()
name = models.CharField(max_length=255, unique=True)
modif_date = models.DateTimeField(auto_now=True)
active = models.BooleanField(default=True)


class Project(models.Model):
id = models.AutoField(primary_key=True)
subsystem_id = models.IntegerField()
name = models.CharField(max_length=255)
modif_date = models.DateTimeField(auto_now=True)
enterprise = models.ForeignKey('Enterprise'
on_delete = CASCADE)
active = models.BooleanField(default=True)

在我看来,需要获取所有活跃的企业并列出它们。我是这样做的:

enterprise_list = Enterprise.objects.annotate(project_count=Count('project')).filter(
Q(active=True) | Q(subsystem_id=-1), project_count__gt=0
)

serializer = EnterpriseSerializer(enterprise_list, many=True)

然后,我的序列化器显示带有一些额外查询的项目列表:

class EnterpriseSerializer(serializers.ModelSerializer):
id = serializers.IntegerField(required=False)
name = serializers.CharField(max_length=255, required=False)
project_list = serializers.SerializerMethodField()

def get_project_list(self, enterprise):
project_list = Project.objects.filter(Q(active=True) | Q(subsystem_id=-1),
enterprise=enterprise)
serializer = ProjectSerializer(project_list, many=True)
return serializer.data

class Meta:
model = Enterprise
fields = ('id', 'name', 'project_list')

这段代码工作正常,但它有一个非常严重的问题——性能。对 Enterprise 的第一个查询返回 ~1500 个对象的列表。然后,对于每个对象,序列化程序执行单个查询以获取项目的额外数据,这会产生约 1500 个查询。

我已经尝试过 prefetch_relatedselect_related 但要么我做错了什么,要么在我的情况下不起作用。

另一方面,我可以先获取项目列表。这可以消除我的计数注释。但我应该按企业对它们进行分组,但据我所知,Django ORM for MySQL 不支持此类操作。我不认为在 python 中解析数据并将其作为 dict 传递给序列化程序是个好主意。

在我的案例中,您能给我一些如何限制查询的提示吗?也许 prefetch/select_related 会对我的情况有所帮助,但如何在这里正确使用它们呢?我正在使用 MySQL 数据库。

最佳答案

您可以按以下方式使用prefetch_related:

from django.db.models import Prefetch

enterprise_list = Enterprise.objects.annotate(project_count=Count('project')).filter(
Q(active=True) | Q(subsystem_id=-1),
project_count__gt=0).prefetch_related(
Prefetch('project_set',
queryset=Project.objects.filter(Q(active=True) | Q(subsystem_id=-1)),
to_attr='projects'
)
)

serializer = EnterpriseSerializer(enterprise_list, many=True)

在serializer.py中

class EnterpriseSerializer(serializers.ModelSerializer):
...

def get_project_list(self, enterprise):
project_list = enterprise.projects
serializer = ProjectSerializer(project_list, many=True)
return serializer.data

关于mysql - Django ORM - 相关模型的 MySQL 查询计数优化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46874586/

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