Reputation: 302
I am making a quiz application using DjangoRestFramework and ReactJS and I am coding my serializers for my Create quiz page.
In my application, I have a Question
model, a Game
model which is the Quiz, and an Option
model.
Here is the data I have that I am deserializing:
data = {
'name': 'Quiz Name',
'questions': {
'text': 'Question 1',
'options':[
{'text': 'option 1', 'is_correct':False},
{'text': 'option 1', 'is_correct':True},
]
}
}
I run this in the shell:
>>> serializer = CreateGameSerializer(data=data)
>>> serializer.is_valid()
False
>>> serializer.errors
{'questions': {'non_field_errors': [ErrorDetail(string='Expected a list of items
but got type "dict".', code='not_a_list')]}}
As you can see, I am getting Expected a list of items but got type "dict"
. I am not sure what this error means and I searched SO but didn't find anything relevant.
I have included some of my models and serializers to help solve the problem.
class Game(models.Model):
name = models.CharField(max_length=100, default='')
code = models.CharField(max_length=100, default=generate_unique_code, unique=True)
host = models.CharField(max_length=50, unique=True)
def __str__(self):
return self.code
class Question(models.Model):
text = models.CharField(max_length=100)
order = models.IntegerField(default=0)
game = models.ForeignKey(Game, on_delete=models.CASCADE, related_name='questions')
def __str__(self):
return self.text
class Option(models.Model):
text = models.CharField(max_length=100)
is_correct = models.BooleanField(default=False)
question = models.ForeignKey(Question, on_delete=models.CASCADE, related_name='options')
def __str__(self):
return self.text
class OptionSerializer(serializers.ModelSerializer):
class Meta:
model = Option
fields = ('text', 'is_correct')
class CreateQuestionSerializer(serializers.ModelSerializer):
options = OptionSerializer(many=True)
class Meta:
model = Question
fields = ('text', 'order', 'options')
def create(self, validated_data):
options_data = validated_data.pop('options')
print(options_data)
question = Question.objects.create(**validated_data)
for option_data in options_data:
Option.objects.create(question=question, **option_data)
class CreateGameSerializer(serializers.ModelSerializer):
questions = CreateQuestionSerializer(many=True)
class Meta:
model = Game
fields = ('votes_to_skip', 'name', 'questions')
def create(self, validated_data):
questions_data = validated_data.pop('questions')
print(questions_data)
game = Game.objects.create(**validated_data)
for question_data in questions_data:
Question.objects.create(game=game, **question_data)
return game
I think I have given enough information at this point. I am a novice at this subject so please be patient with me. Thank you!
Upvotes: 0
Views: 1849
Reputation: 7729
The clue is in these lines:
class CreateGameSerializer(serializers.ModelSerializer):
questions = CreateQuestionSerializer(many=True)
# ...
Because you've set many=True
, the serialiser expects a list of objects, but you are feeding in a single object. Depending on your situation, you have two options: set many=False
and use your data as is, or leave many=True
, and change your data to:
data = {
'name': 'Quiz Name',
'questions': [
{
'text': 'Question 1',
'options':[
{'text': 'option 1', 'is_correct':False},
{'text': 'option 1', 'is_correct':True},
]
}
]
}
Upvotes: 3