I have a nested serializer, the create method does not work. I have searched over the internet and no method worked for me. The most popular one is the one listed below.
models.py
class Displays(models.Model):
id = models.CharField(primary_key=True, max_length=32,
default=generate_uuid)
name = models.CharField(max_length=45, blank=True, null=True)
class OrdersDj(models.Model):
id = models.CharField(primary_key=True, max_length=32,
default=generate_uuid)
class AdsDj(models.Model):
id = models.CharField(primary_key=True, max_length=32,
default=generate_uuid)
order = models.ForeignKey(
OrdersDj, on_delete=models.CASCADE, blank=False, null=True)
display = models.ForeignKey(
Displays, on_delete=models.CASCADE, blank=True, null=True)
serializers.py
class DisplaySerializer(serializers.ModelSerializer):
class Meta:
model = Displays
fields = "__all__"
class AdsSerializer(serializers.ModelSerializer):
display = DisplaySerializer()
def create(self, validated_data):
print("validated_data", validated_data)
display_id = validated_data.pop('display')
display = Displays.objects.get(id=display_id)
ad = Displays.objects.create(display=display, **validated_data)
return ad
class Meta:
model = Ads
fields = "__all__"
class OrderSerializer(serializers.ModelSerializer):
ads = AdsSerializer(source="adsdj_set", many=True)
def create(self, validated_data):
validated_data.pop('adsdj_set')
order = Orders.objects.create(**validated_data)
return order
class Meta:
model = Orders
fields = "__all__"
views.py
class AdsCreate(APIView):
def put(self, request):
print('request.data', request.data)
serializer = serializers.AdsSerializer(data=request.data)
if serializer.is_valid():
serializer.save()
print('serializer.data > serializer.valid', serializer.data)
return Response(serializer.data, status=status.HTTP_201_CREATED)
print('serializer.errors > serializer.invalid', serializer.errors)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
print outs
request.data <QueryDict: {'order': ['18bb2225cf6e407a943f2941072d06de'], 'display': ['91'], 'firstday': ['2021-12-4'], 'lastday': ['2021-12-21'], 'duration': ['17'], 'filetype': ['image/png'], 'originalname': ['Picture1.png'], 'price': ['2550'], 'status': ['0'], 'filehash': ['not available yet'], 'orderByNum': ['-1'], 'imgWidth': ['1061'], 'imgHeight': ['708'], 'image': [<InMemoryUploadedFile: Picture1.png (image/png)>]}>
serializer.errors > serializer.invalid {'display': [ErrorDetail(string='This field is required.', code='required')]}
I am giving the display
field to the serializer that is the id of the display. In the create method I find that display and reference it in the new ad
object. The display field is present in the request.data
and passed to the serializer, the serializer complains that the display
field is not present.
One version of sending json data
{"order":"18bb2225cf6e407a943f2941072d06de","display":{"id":91},"firstday":"2021-12-5","lastday":"2021-12-15","duration":11,"image":{},"filetype":"image/png","originalname":"Picture1.png","price":1650,"status":0,"filehash":"not available yet","orderByNum":-1,"imgWidth":1061,"imgHeight":708}
CodePudding user response:
Try using different serializers for creation and representation.
class AdsCreateSerializer(serializers.ModelSerializer):
class Meta:
model = Ads
fields = "__all__"
class AdsSerializer(serializers.ModelSerializer):
display = DisplaySerializer()
class Meta:
model = Ads
fields = "__all__"
CodePudding user response:
For display
field, AdsSerializer
expects the following structure;
"display": {"id": 91}
whereas you send this;
"display": 91