我有3种型号:
class Project(models.Model):
name = models.CharField(max_length=300, unique=True)
description = models.CharField(
max_length=2000,
blank=True,
null=True,
default=None
)
class QuestionSession(models.Model):
name = models.CharField(
max_length=500, default=None, null=True, blank=True
)
project = models.ForeignKey(
Project,
on_delete=models.CASCADE,
related_name='sessions',
blank=True,
null=True,
default=None
)
class Question(models.Model):
description = models.CharField(max_length=500)
question_session = models.ForeignKey(
QuestionSession,
on_delete=models.CASCADE,
related_name='questions',
blank=True,
null=True,
default=None
)
如您所见,项目包含会话,会话包含问题。 我要实现的目标是获取一个包含会话和许多问题的单个项目。我可以通过2个不同的查询轻松完成此操作,但不能在1个查询中完成。
我的序列化器:
class SingleProjectSerializer(serializers.ModelSerializer):
sessions = MinifiedSessionSerializer(many=True)
class Meta:
model = Project
fields = [
'id',
'name',
'description',
'sessions'
]
class MinifiedSessionSerializer(serializers.ModelSerializer):
questions_number = serializers.IntegerField()
class Meta:
model = QuestionSession
fields = [
'id',
'name',
'questions_number'
]
我曾经在单个查询中捕获会话,例如:
Project.objects.get(id=project_id).sessions.annotate(questions_number=Count('questions'))
但是现在怎么办?我需要先获取项目,然后在会话上进行注释。我不知道该怎么做。我需要这样的查询:
Project.objects.filter(pk=project_id).annotate(sessions__questions_number=Count('sessions__questions'))
答案 0 :(得分:0)
我不认为通过Django ORM可以实现。我能想到的唯一解决方案是改变您要求数据的方式:
sessions = QuestionSession.objects.filter(project_id=project_id).select_related('project').annotate(questions_number=Count('questions'))
project = sessions[0].project
这将最终在单个查询中,但是我假设您想将此project
实例传递给DRF序列化器。在这种情况下,project
对预取的会话一无所知,因此需要单独处理。另外,当特定项目没有关联的会话时会出现问题-sessions[0].project
会引发异常。为了保持代码的整洁,我可能会继续使用您当前的方法(但是,为了将所有内容都保留在一个数据库中,这个问题仍然没有解决。)