6

I am trying to serialise a json payload that has a field with an array, the .is_valid() check is returning true but I am getting KeyError: 'passengers' when I try to do this serializer.data['passengers'] but the other fields work fine (such as booking_number and status).

This is the response.data I am passing to the seralizer:

{'booking_number': 2839, 'passengers': [{'first_name': 'Jack', 'surname': 'Smith', 'email': 'smith@mail.com', 'phone_number': '1234'}], 'status': 'ON_HOLD'} 

My seralizers:

class PassengerSerializer(serializers.ModelSerializer):
    class Meta:
        model = Passenger



class FindBus(serializers.ModelSerializer):
    passengers = PassengerSerializer(read_only=True, many=True)

    class Meta:
        model = Booking
        fields = ('booking_number', 'passengers', 'status')

My models:

class Passenger(models.Model):
    first_name = models.CharField(max_length=25)                                    
    surname = models.CharField(max_length=25)                                       
    email = models.EmailField()                                                     
    phone_number = models.CharField(max_length=12) 


class Booking(models.Model):
    booking_number = models.IntegerField(unique=True)                                                                                           
    passenger = models.ManyToManyField(Passenger)                                   
    status = models.CharField(max_length=10)                                        
    hold_time = models.DateTimeField()  

Any advise on how to get this working would be greatly appreciated.

Btw I was following this: Django rest framework serializing many to many field

Jack
  • 193
  • 1
  • 2
  • 11

1 Answers1

7

If you need to de-serialize fields, you should not use read_only=True:

class FindBus(serializers.ModelSerializer):
    passengers = PassengerSerializer(many=True)
    ...

Note that this won't be enough for saving m2m relationships: as explained in Writable nested serializers, you'll also need to define create() and/or update() methods on your serializer:

class FindBus(serializers.ModelSerializer):
    passengers = PassengerSerializer(many=True)
    ...

    def create(self, validated_data):
        ...

    def update(self, validated_data):
        ...

The reason for the need of the create/update is that you have to decide whether the passenger details that you receive refer to existing objects or need to be created.

You might also need to add fields = ('__all__',) (or specify the fields you're interested in) to your PassengerSerializer:

class PassengerSerializer(serializers.ModelSerializer):
    class Meta:
        model = Passenger
        fields = ('__all__',)
Andrea Corbellini
  • 17,339
  • 3
  • 53
  • 69
  • Adding fields = ('__all__') and removing the read only did the trick. Thanks for the additional information. – Jack May 03 '18 at 21:16