Django Rest Framework - Nested Serializer Help - Cannot assign OrderedDict
I'm working on creating a nested writeable serializer for my project and I'm running into a road block. I'm following the code snippet here DRF Writeable Nested Serializers but I'm running into this error when I try to send my payload to the API endpoint via postman:
Cannot assign "OrderedDict([('first_name', 'Mike'), ('last_name', 'Doe'), ('phone_number', '123-456-7890'), ('company_name', 'Trucking Company')])": "Load.primary_driver" must be a "Driver" instance.
Basically, in this specific scenario I need to be able to create a "Load" object (or in other words, shipment object) as well as create a "Driver" object that is associated with the "Load" one POST request. Driver is a FK in the Load model.
Models.py (load model is at the end)
class Broker(models.Model):
id = models.AutoField(primary_key=True)
first_name = models.CharField(max_length=50)
last_name = models.CharField(max_length=50)
e_mail = models.EmailField(max_length=50)
company_name = models.CharField(max_length=50)
phone_number = models.CharField(max_length=50)
class Meta:
db_table = "Broker"
class Employee(models.Model):
id = models.AutoField(primary_key=True)
first_name = models.CharField(max_length=50)
last_name = models.CharField(max_length=50)
e_mail = models.EmailField(max_length=50)
phone_number = models.CharField(max_length=50)
class Meta:
db_table = "Employee"
class Delivery_Location(models.Model):
id = models.AutoField(primary_key=True)
street_address = models.CharField(max_length=50)
city = models.CharField(max_length=30)
state = models.CharField(max_length=20)
zip_code = models.IntegerField()
class Meta:
db_table = "Delivery Location"
class Pickup_Location(models.Model):
id = models.AutoField(primary_key=True)
street_address = models.CharField(max_length=50)
city = models.CharField(max_length=30)
state = models.CharField(max_length=20)
zip_code = models.IntegerField()
class Meta:
db_table = "Pickup Location"
class Driver(models.Model):
id = models.AutoField(primary_key=True)
first_name = models.CharField(max_length=100)
last_name = models.CharField(max_length=100)
phone_number = models.CharField(max_length=14)
company_name = models.CharField(max_length=50)
def __str__(self):
return self.id
class Meta:
db_table = "Driver"
class Container(models.Model):
id = models.AutoField(primary_key=True)
container_number = models.CharField(max_length=15)
class Meta:
db_table = "Container"
class Load(models.Model):
id = models.AutoField(primary_key=True)
primary_driver = models.ForeignKey(Driver,blank=True,null=True,on_delete=CASCADE)
pickup_location = models.ForeignKey(Pickup_Location,blank=True,null=True,on_delete=CASCADE)
delivery_location = models.ForeignKey(Delivery_Location,blank=True,null=True,on_delete=CASCADE)
booked_by = models.ForeignKey(Employee,blank=True,null=True,on_delete=CASCADE)
broker = models.ForeignKey(Broker,blank=True,null=True,on_delete=CASCADE)
delivery_date = models.DateField('Delivery Date')
delivery_time = models.TimeField('Delivery Time')
pickup_date = models.DateField(default='2000-1-1')
pickup_time = models.TimeField(default='12:00:00')
bnsf_container_number = models.ForeignKey(Container,blank=True, null=True, on_delete=CASCADE)
load_number = models.CharField(max_length=20)
trailer_number = models.IntegerField(default=0000)
seal_number = models.IntegerField(default=0000)
shipment_cost = models.DecimalField(max_digits=6,decimal_places=2, default=0)
shipment_revenue = models.DecimalField(max_digits=6,decimal_places=2, default=0)
def __str__(self):
return self.id
class Meta:
db_table = "Load"
views.py (partial code snippet, but the important piece
class LoadViews(APIView):
def get(self,request,id=None):
if id:
load = Load.objects.get(id=id)
serializer = LoadSerializer2(load)
return Response({"status": "success", "data": serializer.data}, status=status.HTTP_200_OK)
else:
loads = Load.objects.all()
serializer = LoadSerializer2(loads, many=True)
return Response({"status": "success", "data": serializer.data}, status=status.HTTP_200_OK)
def post(self,request):
serializer = LoadSerializer2(data=request.data)
if serializer.is_valid():
serializer.save()
return Response({"status":"success", "data":serializer.data}, status=status.HTTP_200_OK)
else:
return Response({"status": "Error", "data": serializer.errors}, status=status.HTTP_400_BAD_REQUEST)
def patch(self,request,id=None):
load = Load.objects.get(id=id)
serializer = LoadSerializer2(load,data=request.data,partial=True)
if serializer.is_valid():
serializer.save()
return Response({"status": "success", "data": serializer.data})
else:
return Response({"status": "error", "data": serializer.errors})
serializers.py
class ContainerSerializer(serializers.ModelSerializer):
# container_number = serializers.CharField()
class Meta:
model = Container
fields = '__all__'
depth = 1
class DriverSerializer(serializers.ModelSerializer):
class Meta:
model = Driver
fields = '__all__'
depth = 1
class BrokerSerializer(serializers.ModelSerializer):
class Meta:
model = Broker
fields = '__all__'
depth = 1
class EmployeeSerializer(serializers.ModelSerializer):
class Meta:
model = Employee
fields = '__all__'
depth = 1
class DeliveryLocationSerializer(serializers.ModelSerializer):
class Meta:
model = Delivery_Location
fields = '__all__'
depth = 1
class PickupLocationSerializer(serializers.ModelSerializer):
class Meta:
model = Pickup_Location
fields = '__all__'
depth = 1
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = '__all__'
depth = 1
class LoadSerializer2(serializers.ModelSerializer):
primary_driver = DriverSerializer(read_only=False)
bnsf_container_number = ContainerSerializer(read_only=False)
pickup_location = PickupLocationSerializer(read_only=False)
delivery_location = DeliveryLocationSerializer(read_only=False)
broker = BrokerSerializer(read_only=False)
booked_by = EmployeeSerializer(read_only=False)
class Meta:
model = Load
fields = '__all__'
depth = 1
#custom create method for drivers
def create(self, validated_data):
drivers_data = validated_data.pop('primary_driver')
load = Load.objects.create(**validated_data)
for driver_data in drivers_data:
Driver.objects.create(load=load, **driver_data)
return load
json I'm trying to send
{
"primaryDriver": {
"firstName": "Mike",
"lastName": "Doe",
"phoneNumber": "123-456-7890",
"companyName": "Trucking Company"
},
"bnsfContainerNumber": {
"containerNumber": "CFQU1111"
},
"pickupLocation": {
"streetAddress": "9999 Pickup Street",
"state": "Wisconsin",
"zipCode": 55555,
"city": "Madison"
},
"deliveryLocation": {
"streetAddress": "5568 Delivery Street",
"state": "California",
"zipCode": 90210,
"city": "Los Angeles"
},
"broker": {
"firstName": "Postman",
"lastName": "Guy",
"eMail": "plswork@work.com",
"companyName": "Hot Brokers 4 u",
"phoneNumber": "123-456-7890"
},
"bookedBy": {
"firstName": "Dane",
"lastName": "Doe",
"eMail": "danedoe@email.com",
"phoneNumber": "123-456-7890"
},
"deliveryDate": "2021-10-21",
"deliveryTime": "12:00:00",
"pickupDate": "2021-10-09",
"pickupTime": "12:00:00",
"loadNumber": "789045",
"trailerNumber": 776543,
"sealNumber": 545156,
"shipmentCost": "900.00",
"shipmentRevenue": "1500.00"
}