2015-03-13 7 views
7

So habe ich die folgende Struktur:Django REST-Framework verschachtelt Ressourcenschlüssel "id" unaccessible

A ClientFile einen Eigentümer gehört (class name = Kontakt). Ich versuche, eine Clientdatei mithilfe der API zu erstellen. Die Anfrage enthält folgende Daten:

{ 
    name: "Hello!" 
    owner: { 
    id: 1, 
    first_name: "Charlie", 
    last_name: "Watson" 
    } 
} 

Ich habe den Serializer nach meiner Struktur erstellt. Ich hoffe, dass dieser API-Aufruf eine Clientdatei mit dem Namen "Hallo!" und Kontakt ID 1 als Besitzer:

class ContactSerializer(serializers.ModelSerializer): 
    class Meta: 
    model = Contact 
    fields = (
     'id', 
     'first_name', 
     'last_name', 
    ) 

class ClientfileSerializer(serializers.ModelSerializer): 

    owner = ContactSerializer(read_only=False) 

    class Meta(): 
    model = Clientfile 
    fields = (
     'id', 
     'name', 
     'owner', 
    ) 

    def create(self, validated_data): 

    owner = Contact.objects.get(pk=validated_data['owner']['id']) 

Ich komme in die create-Methode. Das einzige Feld, das ich benötige, ist jedoch nicht zugänglich. Wenn ich print ['owner']['first_name'] mache, gibt es "Charlie" zurück. Aber die ID scheint aus einigen Gründen nicht zugänglich zu sein ...

Gründe warum dies passieren kann? Fehle ich etwas? (Ich bin neu in Django)


LÖSUNG: Just fand heraus, dass der Grund, warum ID nicht in erster Linie zeigen, tat, war, weil ich es in den Bereichen wie so zu erklären hatte: Hoffe, das hilft.

class ContactSerializer(serializers.ModelSerializer): 

    id = serializers.IntegerField() # ← Here 

    class Meta: 
    model = Contact 
    fields = (
     'id', 
     'first_name', 
     'last_name', 
    ) 

Antwort

1

In Ordnung Also habe ich einen anderen Ansatz gefunden, der funktioniert. Ich habe einen IntegerField-Serializer für die Besitzerbeziehung hinzugefügt. Ich musste auch die Eigentümerrelation auf read_only = True setzen.

Dies ist die json ich über POST schicken:

{ 
    name: "Hello!" 
    owner_id: 1 
} 

Das ist mein Serializer:

class ClientfileSerializer(serializers.ModelSerializer): 

    owner_id = serializers.IntegerField() 
    owner = ContactSerializer(read_only=True) 

    class Meta(): 
    model = Clientfile 
    fields = (
     'id', 
     'owner_id', 
     'owner', 
    ) 

Es ist als der erste Weg weniger kühl scheint, aber es macht den Job. Plus Ich möchte keinen neuen Besitzer erstellen, sondern nur einen auswählen, der bereits in der Datenbank ist. Also ist es vielleicht semantischer, nur die ID und nicht die vollständige Information über Json zu haben.so etwas wie dieses

7

In Django REST-Framework AutoField Felder (diejenigen, die automatisch generiert werden) werden standardmäßig auf schreibgeschützt. Von the docs:

read_only

Setzen Sie dies auf True, um sicherzustellen, dass das Feld verwendet wird, wenn eine Darstellung der Serialisierung, aber wird nicht verwendet, beim Erstellen oder eine Instanz bei der Deserialisierung zu aktualisieren.

Defaults zu False

Sie können dies durch Drucken der Darstellung in der Shell von inspecting your serializer sehen:

serializer = ClientfileSerializer() 
print repr(serializer) 

du in der extra_kwargs indem read_only=False gegen das id-Feld außer Kraft setzen kann:

class ContactSerializer(serializers.ModelSerializer): 
    class Meta: 
    model = Contact 
    fields = (
     'id', 
     'first_name', 
     'last_name', 
    ) 
    extra_kwargs = {'id': {'read_only': False}} 

class ClientfileSerializer(serializers.ModelSerializer): 

    owner = ContactSerializer(read_only=False) 

    class Meta(): 
    model = Clientfile 
    fields = (
     'id', 
     'name', 
     'owner', 
    ) 
    extra_kwargs = {'id': {'read_only': False}} 
+0

Ich habe es versucht. Es behebt das Problem, aber schafft ein anderes: Jetzt kann ich keinen Kontakt erstellen. Es wird ein Fehler ausgegeben, der besagt, dass das ID-Feld erforderlich ist ... – MonsieurNinja

+0

Haben Sie versucht, schreibgeschützt auch auf das ID-Feld für den Clientfileserializer anzuwenden? – br3w5

+0

Ich habe das gleiche Problem wie @MonsieurNinja, dies macht die ID manuell gesetzt werden muss. – Sem

2

Sie können versuchen:

class YourModelSerializer(serializers.ModelSerializer): 

    class Meta: 
     model = YourModel 
     fields = ('id', 'field1', 'field2') 

    def to_internal_value(self, data): 
     """ 
     Dict of native values <- Dict of primitive datatypes. 
     Add instance key to values if `id` present in primitive dict 
     :param data: 
     """ 
     obj = super(YourModelSerializer, self).to_internal_value(data) 
     instance_id = data.get('id', None) 
     if instance_id: 
      obj['instance'] = YourModel.objects.get(id=instance_id) 
     return obj 

Dann in Datenserialisierer validiert sollten Sie „Instanz“ Schlüssel haben, wenn request.data „id“ Schlüssel hat.

Auch Sie können nur "ID" anstelle der vollständigen Instanz/Objekt hinzufügen.

Verwandte Themen