2014-12-31 9 views
8

Sto tentando di creare una relazione nidificata utilizzando Django Rest Framework 3.0. Ho creato i miei serializzatori e ho tentato di sovrascrivere la funzione create(). I miei modelli sono definiti come segue:Django Rest Framework 3.0: Salvataggio della relazione nidificata, molte-a-uno

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() 

Come noterete, posso avere più prezzi per i miei articoli. I miei serializzatori sono definiti come segue:

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 

Quando provo e POST un nuovo elemento:

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

ottengo il seguente errore:

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

Presumibilmente perché il prezzo serializzatore non ha idea quale sia l'ID del nuovo oggetto. Ho provato a sovrascrivere questa funzionalità nella funzione create() del mio serializzatore, ma sembra che la convalida del serializzatore venga colpita prima che io abbia l'opportunità di creare l'articolo e associarlo al prezzo.

Quindi, come posso creare un nuovo elemento, ottenere l'ID oggetto e quindi creare ciascuno dei nuovi prezzi?

+0

Hai raggiunto il metodo 'create' anche quando pubblichi i tuoi dati? –

+0

@SimonCharette Con il codice pubblicato sopra, no, non sembra che abbia mai colpito la funzione 'create'. Tuttavia, se contrassegno il prezzo come non richiesto e non lo POST nel JSON, la funzione di creazione viene eseguita correttamente. Questo mi porta a credere che la convalida venga richiamata sui dati prima che io abbia l'opportunità di gestirli. Ho provato a sovrascrivere la funzione di validazione senza alcun risultato ... – Julio

+1

Puoi incollare il codice per 'CategorySerializer'. –

risposta

5

Il problema è che il tuo PriceSerializer sta cercando la chiave item perché è specificata nel modello Price. Questo non è immediatamente evidente perché si utilizza Meta.exclude anziché Meta.fields.

class PriceSerializer(serializers.ModelSerializer): 

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

è lo stesso di scrittura

class PriceSerializer(serializers.ModelSerializer): 

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

che lo rende molto chiaro che cosa il problema è. Poiché il campo item sul modello non dispone di empty=True (o null=True) impostato, Django REST Framework automaticamente generates it as a PrimaryKeyRelatedField con required=True. Questo è il motivo per cui stai ricevendo l'errore , perché Django REST Framework non può rilevare automaticamente che proviene da un serializzatore padre che ha già quel campo.

È possibile aggirare questo rimuovendo il campo dal serializzatore, poiché non sembra essere mai necessario.

class PriceSerializer(serializers.ModelSerializer): 

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

Questo non sarà più visualizzare il campo item però, ma ho il sospetto che questo non è in realtà un problema per voi.

+0

Sì, funziona! Un fraintendimento da parte mia su come avrebbe funzionato la serializzazione nidificata. – Julio

Problemi correlati