How to check field for update in DRF?

I have a serializer for a model with a foreign key. The requirement is that when creating a foreign key, it can be installed on any existing object from the associated model, but when updating, the associated object cannot be changed. I can check this in custom update() , but would it be more elegant to use serialization check to check this? But I do not know how to do this. Code example:

 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 
+6
source share
1 answer

You can definitely do this using field validation. How do you check if updating or creating checks for self.instance in the check function. There is a little mention of this in the serializer documentation .

self.instance will hold the existing object and its values, so you can use it for comparison.

I believe this should work for your purposes:

 def validate_spouse(self, value): if self.instance and value != self.instance.spouse: raise serializers.ValidationError("Till death do us part!") return value 

Another way to do this is to override if the field is read_only, if you are updating. This can be done in the __init__ serializer. Like a validator, you are just looking for an instance and if there is data:

 def __init__(self, *args, **kwargs): # Check if we're updating. updating = "instance" in kwargs and "data" in kwargs # Make sure the original initialization is done first. super().__init__(*args, **kwargs) # If we're updating, make the spouse field read only. if updating: self.fields['spouse'].read_only = True 
+7
source

All Articles