2016-03-31 4 views
4

ich einen HTTP PUT Anruf mache die Daten eines Objekts mit einer verschachtelten Beziehung, zu aktualisieren und ich bin durch die folgende Fehler erfüllt:auf PUT Aufruf „<Model> mit diesem <field> bereits vorhanden“ - Django REST-Framework

HTTP 400 Bad Request

"AttributeChoice with this slug already exists."

Der Grund, warum dies ist verwirrend, weil ich einen Anruf HTTP PUT mache und ich erwarte, dass es es als UPDATE zu behandeln und nicht ein CREATE.

Meine Modelle wie folgt aussehen:

class Attribute(models.Model): 
    name  = models.CharField(max_length=100) 
    text_input = models.BooleanField(default=False) 
    slug  = models.SlugField(unique=True) 

class AttributeChoice(models.Model): 
    attribute = models.ForeignKey(Attribute) 
    value  = models.CharField(max_length=100) 
    slug  = models.SlugField(unique=True) 

Meine Serializer wie folgt aussehen:

class AttributeChoiceSerializer(serializers.ModelSerializer): 
    class Meta: 
     model = AttributeChoice 
     fields = '__all__' 
     extra_kwargs = {'id': {'read_only': False}} 

class AttributeSerializer(serializers.ModelSerializer): 
    attributechoice_set = AttributeChoiceSerializer(many=True) 
    class Meta: 
     model = Attribute 
     fields = ('id', 'name', 'text_input', 'slug', 'attributechoice_set') 

    def update(self, instance, validated_data): 
     choice_data = validated_data.pop('attributechoice_set') 
     for choice in choice_data: 

      # If id is within the call, then update the object with matching id 
      if 'id' in choice: 
       try: 
        choice_obj = AttributeChoice.objects.get(pk=choice['id']) 
        choice_obj.value = choice['value'] 
        choice_obj.slug = choice['slug'] 
        choice_obj.attribute = instance 
       # If ID is not found, then create a new object 
       except AttributeChoice.DoesNotExist: 
        choice_obj = AttributeChoice(**choice) 
      # If no ID within the call, create a new object. 
      else: 
       choice_obj = AttributeChoice(**choice) 

      choice_obj.save() 

     return instance 

Debug: Selbst wenn ich die update() Funktion entfernen, bekomme ich immer noch die gleichen Fehler. Ich glaube, der Fehler wird gemeldet, wenn im ViewSet .is_valid() aufgerufen wird. Es ist also nicht die update(), die es verursacht.

Auch, wenn ich attributechoice_set = AttributeChoiceSerializer(many=True) entfernen und umfassen nur die attributechoice_set im fields =(), verschwindet der Fehler, aber ich brauche diese Linie für den Rest des Codes zu arbeiten.

+0

Warum setzen Sie 'read_only = False' für' AttributeChoiceSerializer'? – ilse2005

+0

Sie meinen für die ID? Ich muss die ID in 'valided_data' haben und ich muss sie schreiben können, um sie in' update() 'zu behalten. Ich sehe aber nicht, was es mit dem Slug-Fehler zu tun hat. –

+0

Sie brauchen die ID nicht, Sie können auch den 'slug' verwenden, um das Objekt zu erhalten. Möglicherweise überprüft die Validierung, ob Objekte mit dieser ID und diesem Slug erstellt werden können. – ilse2005

Antwort

5

Selbst wenn Sie ein Update durchführen, heißt das nicht, dass die verschachtelten Daten nur aktualisiert werden.

Sie sagen nur, dass Sie das oberste Objekt aktualisieren möchten.

In einigen Fällen entfernen oder erstellen Sie neue verschachtelte Objekte, während Sie das oberste verschachteln.

Daher berücksichtigt DRF standardmäßig verschachtelte Objekte für die Erstellung. Sie können explizit dieses Problem umgehen, indem die eindeutige Einschränkung auf dem verschachtelten Serializer entfernen:

class AttributeChoiceSerializer(serializers.ModelSerializer): 
    class Meta: 
     model = AttributeChoice 
     fields = '__all__' 
     extra_kwargs = { 
      'id': {'read_only': False}, 
      'slug': {'validators': []}, 
     } 
0

Ich denke, es ist wegen des Validierer ist.

Like:

Django rest serializer Breaks when data exists

Als meine Lösung, markiere ich dieses verschachtelte Feld read_only=True, Und mein eigenes Update tun, Funktion erstellen self.initial_data für den Zugriff auf mich zu handhaben.

Verwandte Themen