2014-12-31 14 views
8

Ich versuche, eine verschachtelte Beziehung mit Django Rest Framework 3.0 zu erstellen. Ich habe meine Serialisierer erstellt und versucht, die create()-Funktion zu überschreiben. Meine Modelle sind wie folgt definiert:Django Rest Framework 3.0: Verschachtelte, viele-zu-eins-Beziehung speichern

class Item(models.Model): 
    user = models.ForeignKey(settings.AUTH_USER_MODEL) 
    name = models.CharField(max_length=200) 
    description = models.CharField(max_length=1000) 
    categories = models.ManyToManyField(Category, null=True, blank=True) 

class Price(models.Model): 
    user = models.ForeignKey(settings.AUTH_USER_MODEL) 
    item = models.ForeignKey(Item, related_name='prices') 
    name = models.CharField(max_length=100) 
    cost = models.FloatField() 

Wie Sie feststellen werden, kann ich mehrere Preise für meine Artikel haben. Meine Serializer sind wie folgt definiert:

class PriceSerializer(serializers.ModelSerializer): 
    class Meta: 
     model = Price 
     owner = serializers.Field(source='owner.username') 
     exclude = ('user',) 

class ItemSerializer(serializers.ModelSerializer): 
    prices = PriceSerializer(many=True, required=False) 
    categories = CategorySerializer(many=True, required=False) 

    class Meta: 
     model = Item 
     owner = serializers.Field(source='owner.username') 
     fields = ('id', 'name', 'description', 'prices', 'categories') 

    def create(self, validated_data): 
     user = validated_data.get('user') 

     # Get our categories 
     category_data = validated_data.pop('categories') 

     # Create our item 
     item = Item.objects.create(**validated_data) 

     # Process the categories. We create any new categories, or return the ID of existing 
     # categories. 
     for category in category_data: 
      category['name'] = category['name'].title() 
      category, created = Category.objects.get_or_create(user=user, **category) 
      item.categories.add(category.id) 

     item.save() 

     return item 

Wenn ich versuche, und POST ein neues Element:

{ 
    "name": "Testing", 
    "description": "This is a test", 
    "categories": [ 
     { 
      "name": "foo" 
     }, 
     { 
      "name": "bar" 
     } 
    ], 
    "prices": [ 
     { 
      "name": "Red", 
      "cost": 10 
     } 
    ] 
} 

ich die folgende Fehlermeldung erhalten:

{ 
    "prices": [ 
     { 
      "item": [ 
       "This field is required." 
      ] 
     } 
    ] 
} 

Vermutlich, weil der Preis Serializer nicht hat Idee, was die ID des neuen Artikels ist. Ich habe versucht, diese Funktionalität in der create() Funktion meines Serialisierers zu überschreiben, aber es scheint, als ob die Validierung des Serialisers getroffen wird, bevor ich die Möglichkeit habe, das Element zu erstellen und es mit dem Preis zu verknüpfen.

Also - Wie erstelle ich einen neuen Artikel, bekomme die Artikel-ID und dann jeden der neuen Preise erstellen?

+0

Erreichen Sie die Methode create beim Übermitteln Ihrer Daten? –

+0

@SimonCharette Mit dem Code oben, nein, es scheint nicht, dass ich jemals die 'create' Funktion getroffen habe. Wenn ich jedoch den Preis als nicht erforderlich markieren und nicht im JSON POST es, wird die create-Funktion einwandfrei ausgeführt. Dies führt mich zu der Annahme, dass die Validierung der Daten aufgerufen wird, bevor ich die Möglichkeit habe, damit umzugehen. Ich habe versucht, die Validierungsfunktion ohne Erfolg zu überschreiben ... – Julio

+1

Können Sie den Code für 'CategorySerializer' einfügen. –

Antwort

5

Das Problem ist, dass Ihr PriceSerializer nach dem Schlüssel item sucht, weil es auf dem Modell Price angegeben ist. Dies ist nicht sofort offensichtlich, da Sie Meta.exclude anstelle von Meta.fields verwenden.

class PriceSerializer(serializers.ModelSerializer): 

    class Meta: 
     model = Price 
     exclude = ('user',) 

ist die gleiche wie

class PriceSerializer(serializers.ModelSerializer): 

    class Meta: 
     model = Price 
     fields = ('id', 'item', 'name', 'cost',) 

schreiben, die sehr deutlich macht, was Ihr Problem ist. Da Ihr item Feld auf dem Modell empty=True (oder null=True) nicht festgelegt hat, wird Django REST Framework automatisch generates it as a PrimaryKeyRelatedField mit required=True. Aus diesem Grund erhalten Sie den This field is required erforderlichen Fehler, da Django REST Framework nicht automatisch erkennen kann, dass es von einem übergeordneten Serialisierungsprogramm stammt, das dieses Feld bereits enthält.

Sie können dies umgehen, indem Sie das Feld aus dem Serializer entfernen, da es scheinbar nie benötigt wird.

class PriceSerializer(serializers.ModelSerializer): 

    class Meta: 
     model = Price 
     fields = ('id', 'name', 'cost',) 

Dies wird angezeigt, nicht mehr das item Feld zwar, aber ich vermute, dies für Sie nicht wirklich ein Problem.

+0

Yup, das funktioniert! Ein Missverständnis meinerseits darüber, wie die verschachtelte Serialisierung funktionieren würde. – Julio

Verwandte Themen