DRF: How can I validate data vs instance when many=True?
I am using a DRF serializer to update data in bulk. This is how I instantiate the serializer:
# Order incoming data and DB instances
data = sorted(data, key=lambda x: x["id"])
instances = WorksheetChecklistItem.objects.filter(id__in=(row["id"] for row in data)).order_by("id")
# Serialize and save
serializer = update.WorksheetChecklistItemSerializer(instance=instances, data=data, many=True)
if not serializer.is_valid():
# ... more logic ...
And this is the serializer:
class WorksheetChecklistItemSerializer(serializers.ModelSerializer):
class Meta:
model = WorksheetChecklistItem
fields = ["id", "value", "outcome"]
def update(self, instance, validated_data):
instance.outcome = validated_data.get("outcome", instance.outcome)
instance.value = validated_data.get("value", instance.value)
instance.done = instance.outcome is not None
instance.save()
return instance
def validate(self, data):
"""Custom validation for the checklist item."""
instance = self.instance
if not instance:
raise serializers.ValidationError("Instance is required for validation") # Only update is allowed
# Validate "must" condition
if instance.must and not data.get("done"):
raise serializers.ValidationError(f"Checklist item {instance.id} is required but not completed.")
# Validate that value is a number
if instance.check_type == WorksheetChecklistItem.CheckType.VALUE and not isinstance(data.get("value"), (int, float)):
raise serializers.ValidationError(f"Checklist item {instance.id} requires a numeric value.")
return data
So I'm relying on the default ListSerializer class that is triggered when the serializer is instantiated with the many=True argument.
My validation fails because the validate method does not have an "instance" argument like the update method does; and self.instance is the entire queryset, not only the "current" instance.
So this instruction fails:
if instance.must
because "instance" is a queryset and doesn't have a "must" attribute.
At the moment, my only solution is to get the object from the database using the id I have in the "data" argument; but that would result in a lot of queries.
Is there any way to validate data vs instance?