问题描述
我无法在序列化程序列表的多对多字段中检索答案选择 ID 或检索
相反,我得到了 quiz.Choice.None
我明白为什么会这样,但是如果我从序列化程序中删除 answer = serializers.CharField()
这一行。创建问题时出现错误:
{
"answer": [
"Incorrect type. Expected pk value,received str."
]
}
我无法从前端传递答案,我希望检索 "answer": [2,3]
而不是 None 并且我也知道如果我从序列化程序中删除 answer = serializers.CharField()
这一行。它解决了问题,但它引发了另一个问题,即我无法传递甚至尚未创建的答案选择 ID。此类问题的最佳解决方案是什么?我还尝试对空数组进行答案验证。但这甚至不起作用。
{
"id": 5,"label": "Question 1","answer": "quiz.Choice.None","explanation": "New Added fhfd","mode": 1,"subtopic": 2,"choice": [
{
"id": 5,"option": "option 6 Edited New One","question": 5
},{
"id": 6,"option": "option 5 Hllloo Sakib","question": 5
}
]
}
我的模型:
# Question Mode
MODE = ((0,"Easy"),(1,"Medium"),(2,"Hard"))
class Question(models.Model):
"""Question Model"""
label = models.CharField(max_length=1024)
answer = models.ManyToManyField("Choice",related_name="quesans",blank=True)
explanation = models.TextField(blank=True)
mode = models.IntegerField(choices=MODE,default=0)
subtopic = models.ForeignKey(
"motherset.Subtopic",on_delete=models.CASCADE,related_name="question"
)
created_time = models.DateTimeField(auto_Now_add=True,blank=True)
def __str__(self):
return self.label
class Choice(models.Model):
"""Question Option"""
option = models.CharField(max_length=1024)
question = models.ForeignKey(
Question,related_name="choice",blank=True,null=True
)
def __str__(self):
return self.option
在 Serializers.py 中:
class ChoiceSerializer(serializers.ModelSerializer):
"""Serializers for Question Choice"""
id = serializers.IntegerField()
class Meta:
model = Choice
fields = ("id","option","question")
class CreateQuestionSerializer(serializers.ModelSerializer):
choice = ChoiceSerializer(many=True,partial=True)
answer = serializers.CharField()
class Meta:
model = Question
fields = ("id","label","answer","explanation","mode","subtopic","choice")
extra_kwargs = {"answer": {"validators": []}}
def create(self,validated_data):
"""Create Model With nested Serializer"""
choices_data = validated_data.pop("choice")
answerString = validated_data.pop("answer",[])
answer = literal_eval(answerString)
print(answer)
print(type(answer))
question = Question.objects.create(**validated_data)
for choice_data in choices_data:
choice_created = Choice.objects.create(
option=choice_data["option"],question=question
)
for choice_option in answer:
if choice_option == choice_created.option:
question.answer.add(choice_created)
question.save()
return question
def update(self,instance,validated_data):
"""Update Instance including nested serializer"""
choices_data = validated_data.pop("choice",None)
if choices_data is not None:
for choice_data in choices_data:
choice = Choice.objects.get(pk=choice_data["id"])
choice.option = choice_data["option"]
choice.save()
return super().update(instance,validated_data)
在 api.py 中:
class CreateQuestionView(viewsets.ModelViewSet):
serializer_class = CreateQuestionSerializer
queryset = Question.objects.all()
在 axios 帖子正文中:
{
"label": "Label q","explanation": "","answer": ["option 7","option 8"],"choice": [
{
"id":3324242,"option": "option 7"
},{
"id":3324245,"option": "option 8"
},{
"id":3324248,"option": "option 9"
}
]
}
解决方法
answer
由其 pk
引用,而不是由 option
引用。
像下面这样的调用应该可以工作,您提交选择的 PK 而不是选项文本:
{
"label": "Label q","explanation": "","answer": [7,8],"mode": 1,"subtopic": 2,"choice": [
{
"id":3324242,"option": "option 7"
},{
"id":3324245,"option": "option 8"
},{
"id":3324248,"option": "option 9"
}
]
}
,
更新
我将 Modelviewset 类更新为:
class CreateQuestionView(viewsets.ModelViewSet):
serializer_class = CreateQuestionSerializer
queryset = Question.objects.all()
def retrieve(self,request,*args,**kwargs):
instance = self.get_object()
serializer = self.get_serializer(instance)
answer = []
for ans in instance.answer.all():
answer.append(ans.id)
newDict = {}
newDict.update(serializer.data)
newDict.update({"answer": answer})
return Response(newDict)
def list(self,**kwargs):
queryset = self.filter_queryset(self.get_queryset())
page = self.paginate_queryset(queryset)
if page is not None:
serializer = self.get_serializer(page,many=True)
return self.get_paginated_response(serializer.data)
serializer = self.get_serializer(queryset,many=True)
newList = []
for question in serializer.data:
q = Question.objects.get(pk=question["id"])
answer = []
for ans in q.answer.all():
answer.append(ans.id)
newDict = {}
newDict.update(question)
newDict.update({"answer": answer})
newList.append(newDict)
return Response(newList)
现在一切正常。感谢我自己。 :v