【发布时间】:2018-04-03 03:06:36
【问题描述】:
我有两个相关的模型,如下所示:
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_related 和select_related,但要么我做错了,要么在我的情况下不起作用。
另一方面,我可以先获取项目列表。这可以消除我的计数注释。但我应该按企业对它们进行分组,但据我所知,Django ORM for MySQL 不支持此类操作。我不认为在 python 中解析数据并将其作为 dict 传递给序列化程序是一个好主意。
您能否给我一些提示,在我的情况下如何限制查询?也许prefetch/select_related 对我的情况会有所帮助,但是如何在这里正确使用它们呢?我正在使用 MySQL 数据库。
【问题讨论】:
标签: mysql django orm django-rest-framework