2016-09-20 16 views
5

私は外部キーを持つモデルのシリアライザを持っています。要件は、作成時に、関連するモデルの既存のオブジェクトに外部キーを設定できますが、更新時に関連するオブジェクトを変更することはできません。私はカスタムupdate()でこれをチェックできますが、これをチェックするためにシリアライザの検証を使用する方がよりエレガントでしょうか?しかし、私はどのように確かではありません。例コード:DRFで更新時のフィールドを検証する方法は?

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 

答えて

7

これは間違いなくフィールドの検証を使用して行うことができます。それが更新かどうかを確認する方法は、検証機能でself.instanceをチェックしています。少し言われているのはin the serializer documentationです。

self.instanceは、既存のオブジェクトとその値を保持するため、比較するために使用できます。

私は、これはあなたの目的のために働くべきだと考え:

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

これを行うための別の方法は、あなたが更新している場合、フィールドがREAD_ONLYである場合に上書きすることです。これはシリアライザの__init__で行うことができます。バリデータと同様に、単にインスタンスを探し、データがあるかどうかを調べるだけです:

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 
関連する問題