Jack
Jack

Reputation: 343

Django Rest framework Serialize many to many field

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': '[email protected]', '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

Upvotes: 7

Views: 8824

Answers (1)

Andrea Corbellini
Andrea Corbellini

Reputation: 17781

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__',)

Upvotes: 7

Related Questions