Migrating primary key to UUIDField causes serializer validation issues
For application-specific performance considerations, we recently decided to migrate our primary keys from BigAutoField to UUIDField.
class BaseModel(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
All models extend BaseModel. For example:
class Message(BaseModel):
messenger = models.ForeignKey('core.PersonBusinessUmbrella', on_delete=models.CASCADE)
There is a lot of (writable) nesting involved in our serializers. For example:
class CustomModelSerializer(ModelSerializer):
created_at = serializers.DateTimeField(required=False, allow_null=True)
class MessageSerializer(CustomModelSerializer):
messenger = PersonBusinessUmbrellaSerializer(required=False)
class PersonBusinessUmbrellaSerializer(CustomModelSerializer):
business_umbrella = BusinessUmbrellaSerializer()
class BusinessUmbrellaSerializer(CustomModelSerializer):
...
All data retrieval continues to work normally. However, when sending POST/PUT requests with that same data structure to the corresponding ModelViewSet, issues arise.
POST-ing a new Message, including nested models
{
"relatedFiles": [],
"order": "00e204d9-ef4e-482c-bd5d-8a4129450728",
"messenger": {
"id": "b3756ec6-d793-4a4e-88f7-5826e38f83d3",
"createdAt": "2024-07-09T09:38:22.906",
"updatedAt": "2024-07-09T09:38:22.906",
"person": {
"id": "445da4a0-9ab6-4bad-9d83-40e9215d269f",
"createdAt": "2024-07-09T09:38:22.229",
"updatedAt": "2024-07-09T09:38:22.229",
"businessUmbrellas": [
{
"id": "b0cfda01-80df-456c-9603-1b9d68b67270",
"createdAt": "2024-07-09T09:38:22.129",
"updatedAt": "2024-07-09T09:38:22.129",
"name": "Bouwman",
"comment": null
}
],
"firstName": "Adam",
"lastName": "Willems",
"phoneNumber": "0611666677"
},
"businessUmbrella": {
"id": "b0cfda01-80df-456c-9603-1b9d68b67270",
"createdAt": "2024-07-09T09:38:22.129",
"updatedAt": "2024-07-09T09:38:22.129",
"name": "Bouwman",
"comment": null
},
"email": "[email protected]",
"phoneNumber": null,
"roles": [
{
"id": "a75be758-b0f1-45b3-8c8b-f77136d133b0",
"createdAt": "2024-07-09T09:38:25.928",
"updatedAt": "2024-07-09T09:38:25.928",
"personBusinessUmbrella": "b3756ec6-d793-4a4e-88f7-5826e38f83d3",
"type": 2,
"defaultMachine": {
"id": "3fc4f1ce-9293-4d8c-a5f8-fa710024815e",
"createdAt": "2024-07-09T09:38:22.198",
"updatedAt": "2024-07-09T09:38:22.198",
"name": "Heftruck-hebben"
}
}
]
},
"body": "abc"
}
Response
{
"messenger": {
"nonFieldErrors": [
"‘OrderedDict({'created_at': datetime.datetime(2024, 7, 9, 9, 38, 22, 129000), 'uuid': UUID('51007185-c51b-4dd9-b5ff-d615706abc25'), 'name': 'Bouwman', 'comment': None})’ is geen geldige UUID."
]
}
}
Whereas with BigAutoField the serializer validation would understand that the nested OrderedDict represented an entity, it now insists on receiving an actual UUID value.
Could you provide a full example, with also the view and some fields in the serializers? Or at least a minimal reproducible example.
This is quite strange, because it seems like the code is using a serializer in which your nested serializer is not used, and thus it requires you to provide an UUID instead of the model.
Here is an expample derived from a project of mine:
# models.py
class Node(models.Model):
id = models.UUIDField(default=uuid.uuid4, primary_key=True)
title = models.CharField(max_length=256)
is_condition = models.BooleanField(default=False)
description = models.TextField(blank=True, default='')
# serializers.py
class NodeSerializer(serializers.ModelSerializer):
class Meta:
model = Node
fields = serializers.ALL_FIELDS
class NestedSerializer(serializers.Serializer):
node = NodeSerializer()
# code
ser = MySerializer(
data={
"node": {
"id": "724377d8-ab79-41ec-b909-0242ac120002",
"title": "Step 0",
"is_condition": True,
"description": "example",
}
}
)
ser.is_valid()
# > True
Thanks for the follow-up @sevdog - I'll close this for now.