I have a serializer for a model with a foreign key. The requirement is that on create, foreign key can be set to any existing object from the related model, but on update the related object cannot be changed. I can check this in the custom update()
, but it would be more elegant to use serializer validation to check for this? But I am not sure how. Example code:
class Person(models.Model):
name = models.CharField(max_length=256)
spouse = models.ForeignKey(Person)
class PersonSerializer(serializers.ModelSerializer):
class Meta:
model = Person
# this is how I know how to do this
def create(self, validated_data):
try:
spouse = Person.objects.get(pk=int(validated_data.pop('spouse')))
except Person.DoesNotExist:
raise ValidationError('Imaginary spouses not allowed!')
return Person.objects.create(spouse=spouse, **validation_data)
def update(self, person, validated_data):
if person.spouse.pk != int(validated_data['spouse']):
raise ValidationError('Till death do us part!')
person.name = validation_data.get('name', person.name)
person.save()
return person
# the way I want to do this
def validate_spouse(self, value):
# do validation magic
You can definitely do this using the validation on a field. The way you'd check if it's an update vs. creation is checking for
self.instance
in the validation function. There's a bit mentioned about it in the serializer documentation.self.instance
will hold the existing object and it's values, so you can then use it to compare against.I believe this should work for your purposes:
Another way to do this is to override if the field is read_only if you're updating. This can be done in the
__init__
of the serializer. Similar to the validator, you'd simply look for an instance and if there's data: