Rayyan
Rayyan

Reputation: 302

Expected a list of items but got dict djangorestframework

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.

The Problem

My data

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.

My Files

I have included some of my models and serializers to help solve the problem.

models.py

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

serializers.py





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

Answers (1)

Igor Moraru
Igor Moraru

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

Related Questions