带有嵌套序列化器的 Django 反向外键给出多个结果
Django Reverse Foreign key with nested serializer gives multiple results
如何使用反向外键关系生成左外连接查询并将其映射到嵌套序列化程序?我想过滤多个外键的结果。
models.py
class Question(models.Model):
question_name = models.CharField(max_length=1024)
class Paper(models.Model):
paper_name = models.CharField(max_length=128)
class Answer(models.Model):
score = models.IntegerField()
question_id = models.ForeignKey(Question, related_name='answer_questions')
paper_id = models.ForeignKey(Paper, related_name='answer_papers')
class Meta:
unique_together = ("question_id", "paper_id")
serializers.py
class PaperSerializer(serializers.ModelSerializer):
class Meta:
fields = ('id', 'paper_name')
model = Paper
class AnswerSerializer(serializers.ModelSerializer):
class Meta:
fields = ('id', 'score', 'question_id', 'paper_id')
model = Answer
class QuestionSerializer(serializers.ModelSerializer):
answer_questions = AnswerSerializer(many=True, allow_null=True)
class Meta:
fields = ('id', 'question_name', 'answer_questions')
model = Question
views.py
class QuestionList(generics.ListAPIView):
def get_queryset(self):
paper_id = self.kwargs['pk']
queryset = Question.objects.filter(answer_questions__paper_id=paper_id, answer_questions__question_id=F('id'))
return queryset
serializer_class = QuestionSerializer
我的url是
localhost/papers/1/questions/
预期输出:
(1) 包含 对应 question_id 和 paper_id 答案对象的所有问题列表(单个答案对象) 嵌入其中。
(2) 列表应包括所有问题,无论是否已回答(如果问题未回答,应返回答案对象为空的问题)即左外连接
[
{
"id": 1,
"question_id": 1,
"answer_questions": [
{
"id": 24,
"score": 5,
"question_id": 1,
"paper_id": 1
},
{
"id": 27,
"score": 8,
"question_id": 1,
"paper_id": 2
},
{
"id": 28,
"score": 6,
"question_id": 1,
"paper_id": 3
}
]
}
]
当前输出:
(1) 我得到了特定 question_id 的多个答案对象,包括所有 paper_id。即对于 question_id = 1 和 paper_id = 2,我的输出显示带有答案对象的问题 question_id = 1 不过滤 paper_id.
(2) 只回答问题(因为query是inner join query)
[
{
"id": 1,
"question_id": 1,
"answer_questions": [
{
"id": 24,
"score": 5,
"question_id": 1,
"paper_id": 1
}
]
}
]
如果不是很好的实现方式,请提出更好的优化方式。
我认为如果稍微更改 get_quesyset()
方法,您将获得所需的输出。
class QuestionList(generics.ListAPIView):
def get_queryset(self):
<b>return Question.objects.all()</b>
serializer_class = QuestionSerializer
当您访问 QuestionList list api
时,您将得到如下输出
[
{
"id": 4,
"question_name": "qus-1",
"answer_questions": [
{
"id": 5,
"score": 50,
"question_id": 4,
"paper_id": 4
},
{
"id": 6,
"score": 10,
"question_id": 4,
"paper_id": 5
}
]
},
{
"id": 5,
"question_name": "qus-2",
"answer_questions": []
},
{
"id": 6,
"question_name": "que-3",
"answer_questions": [
{
"id": 7,
"score": 342,
"question_id": 6,
"paper_id": 4
}
]
}
]
更新-1
如下更改序列化程序
class QuestionSerializer(serializers.ModelSerializer):
<b>answer_questions = serializers.SerializerMethodField()
def get_answer_questions(self, question):
paper_id = self.context['view'].kwargs.get('paper_id')
return AnswerSerializer(question.answer_questions.filter(paper_id=paper_id), many=True).data</b>
class Meta:
fields = ('id', 'question_name', 'answer_questions')
model = Question
如何使用反向外键关系生成左外连接查询并将其映射到嵌套序列化程序?我想过滤多个外键的结果。
models.py
class Question(models.Model):
question_name = models.CharField(max_length=1024)
class Paper(models.Model):
paper_name = models.CharField(max_length=128)
class Answer(models.Model):
score = models.IntegerField()
question_id = models.ForeignKey(Question, related_name='answer_questions')
paper_id = models.ForeignKey(Paper, related_name='answer_papers')
class Meta:
unique_together = ("question_id", "paper_id")
serializers.py
class PaperSerializer(serializers.ModelSerializer):
class Meta:
fields = ('id', 'paper_name')
model = Paper
class AnswerSerializer(serializers.ModelSerializer):
class Meta:
fields = ('id', 'score', 'question_id', 'paper_id')
model = Answer
class QuestionSerializer(serializers.ModelSerializer):
answer_questions = AnswerSerializer(many=True, allow_null=True)
class Meta:
fields = ('id', 'question_name', 'answer_questions')
model = Question
views.py
class QuestionList(generics.ListAPIView):
def get_queryset(self):
paper_id = self.kwargs['pk']
queryset = Question.objects.filter(answer_questions__paper_id=paper_id, answer_questions__question_id=F('id'))
return queryset
serializer_class = QuestionSerializer
我的url是 localhost/papers/1/questions/
预期输出: (1) 包含 对应 question_id 和 paper_id 答案对象的所有问题列表(单个答案对象) 嵌入其中。 (2) 列表应包括所有问题,无论是否已回答(如果问题未回答,应返回答案对象为空的问题)即左外连接
[
{
"id": 1,
"question_id": 1,
"answer_questions": [
{
"id": 24,
"score": 5,
"question_id": 1,
"paper_id": 1
},
{
"id": 27,
"score": 8,
"question_id": 1,
"paper_id": 2
},
{
"id": 28,
"score": 6,
"question_id": 1,
"paper_id": 3
}
]
}
]
当前输出: (1) 我得到了特定 question_id 的多个答案对象,包括所有 paper_id。即对于 question_id = 1 和 paper_id = 2,我的输出显示带有答案对象的问题 question_id = 1 不过滤 paper_id. (2) 只回答问题(因为query是inner join query)
[
{
"id": 1,
"question_id": 1,
"answer_questions": [
{
"id": 24,
"score": 5,
"question_id": 1,
"paper_id": 1
}
]
}
]
如果不是很好的实现方式,请提出更好的优化方式。
我认为如果稍微更改 get_quesyset()
方法,您将获得所需的输出。
class QuestionList(generics.ListAPIView):
def get_queryset(self):
<b>return Question.objects.all()</b>
serializer_class = QuestionSerializer
当您访问 QuestionList list api
时,您将得到如下输出
[
{
"id": 4,
"question_name": "qus-1",
"answer_questions": [
{
"id": 5,
"score": 50,
"question_id": 4,
"paper_id": 4
},
{
"id": 6,
"score": 10,
"question_id": 4,
"paper_id": 5
}
]
},
{
"id": 5,
"question_name": "qus-2",
"answer_questions": []
},
{
"id": 6,
"question_name": "que-3",
"answer_questions": [
{
"id": 7,
"score": 342,
"question_id": 6,
"paper_id": 4
}
]
}
]
更新-1
如下更改序列化程序
class QuestionSerializer(serializers.ModelSerializer):
<b>answer_questions = serializers.SerializerMethodField()
def get_answer_questions(self, question):
paper_id = self.context['view'].kwargs.get('paper_id')
return AnswerSerializer(question.answer_questions.filter(paper_id=paper_id), many=True).data</b>
class Meta:
fields = ('id', 'question_name', 'answer_questions')
model = Question