2016-09-20 12 views
5

Mam serializator dla modelu z kluczem obcym. Warunkiem jest, aby podczas tworzenia obcy klucz mógł zostać ustawiony na dowolny istniejący obiekt z powiązanego modelu, ale po aktualizacji nie można zmienić powiązanego obiektu. Mogę to sprawdzić w niestandardowym update(), ale byłoby bardziej elegancko zastosować sprawdzanie serializera, aby to sprawdzić? Ale nie jestem pewien jak. Przykładowy kod:Jak sprawdzić poprawność pola przy aktualizacji w 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 

Odpowiedz

7

Z pewnością można to zrobić za pomocą walidacji na polu. Sposób sprawdzania, czy jest to aktualizacja w porównaniu do kreacji, polega na sprawdzeniu, czy w funkcji sprawdzania poprawności jest self.instance. Jest trochę o tym wspomniany in the serializer documentation.

self.instance Zatrzyma istniejący obiekt i jego wartości, dzięki czemu można go użyć do porównania.

Wierzę, że to powinno działać dla swoich celów:

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

Innym sposobem, aby to zrobić, aby zastąpić, jeśli pole jest READ_ONLY przypadku aktualizacji. Można to zrobić w serializatorze __init__. Podobnie jak w przypadku walidatora, po prostu poszukaj instancji i czy istnieją dane:

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 
Powiązane problemy