2016-05-15 12 views
11

Ich habe ein Problem beim Aktualisieren eines verschachtelten Objekts.Django-Ruhe-Rahmen. Verschachteltes Objekt aktualisieren

So habe ich ein Modell, die Struktur zu diesem ähnlich ist:

class Invoice(models.Model): 
    nr = models.CharField(max_length=100) 
    title = models.CharField(max_length=100) 

class InvoiceItem(models.Model): 
    name = models.CharField(max_length=100) 
    price = models.FloatField() 
    invoice = models.ForeignKey(Invoice, related_name='items') 

ich Kind von den Eltern-Objekte erstellen muß, und was ich damit meine, ist InvoiceItems direkt zu erstellen, wenn ein Invoice Objekt erstellen . Zu diesem Zweck habe ich schrieb folgende Serializer:

class InvoiceItemSerializer(serializers.ModelSerializer): 
    invoice = serializers.PrimaryKeyRelatedField(queryset=Invoice.objects.all(), required=False) 
    class Meta: 
     model = InvoiceItem 


class InvoiceSerializer(serializers.ModelSerializer): 
    items = InvoiceItemSerializer(many=True) 

    class Meta: 
     model = Invoice 

    def create(self, validated_data): 
     items = validated_data.pop('items', None) 
     invoice = Invoice(**validated_data) 
     invoice.save() 
     for item in items: 
      InvoiceItem.objects.create(invoice=invoice, **item) 
     return invoice 

Bisher erstellen/lesen/löschen Methoden funktionieren einwandfrei, mit Ausnahme der update. Ich denke, die folgende Logik sollte korrekt sein, aber es fehlt etwas.

def update(self, instance, validated_data): 
    instance.nr = validated_data.get('nr', instance.nr) 
    instance.title = validated_data.get('title', instance.title) 
    instance.save() 

    # up till here everything is updating, however the problem appears here. 
    # I don't know how to get the right InvoiceItem object, because in the validated 
    # data I get the items queryset, but without an id. 

    items = validated_data.get('items') 
    for item in items: 
     inv_item = InvoiceItem.objects.get(id=?????, invoice=instance) 
     inv_item.name = item.get('name', inv_item.name) 
     inv_item.price = item.get('price', inv_item.price) 
     inv_item.save() 

    return instance 

Jede Hilfe würde wirklich geschätzt werden.

+1

Sie werden wahrscheinlich das PK als Teil der Nutzlast übergeben müssen. – dkarchmer

+0

Ich vergehe, aber es ist nicht in 'valided_data' enthalten – dimmg

+0

Können Sie Ihre Nutzlast zeigen? – dkarchmer

Antwort

11

Dies ist die Art, wie ich die Aufgabe erledigt habe:

Ich habe ein id Feld zu InvoiceItemSerializer

012 hinzugefügt
class InvoiceItemSerializer(serializers.ModelSerializer): 
    ... 
    id = serializers.IntegerField(required=False) 
    ... 

Und die Update-Methode für die InvoiceSerializer

def update(self, instance, validated_data): 
    instance.nr = validated_data.get('nr', instance.nr) 
    instance.title = validated_data.get('title', instance.title) 
    instance.save() 

    items = validated_data.get('items') 

    if items: 
     for item in items: 
      item_id = item.get('id', None) 
      if item_id: 
       inv_item = InvoiceItem.objects.get(id=item_id, invoice=instance) 
       inv_item.name = item.get('name', inv_item.name) 
       inv_item.price = item.get('price', inv_item.price) 
       inv_item.save() 
      else: 
       InvoiceItem.objects.create(account=instance, **item) 

    return instance 

Auch in der create Methode ich knalle die id wenn es übergeben wird.

+0

Danke für die Probe. Aber bitte vergiss nicht, 'DoesNotExist' Ausnahme zu fangen, die' inv_item = InvoiceItem.objects.get (id = item_id, invoice = instance) 'auslösen kann. – Merka

2

Ich stieß in letzter Zeit auf das gleiche Problem. Die Art, wie ich behandelt es war, die id zu zwingen, ein erforderliches Feld zu sein:

class MySerializer(serializers.ModelSerializer): 

    class Meta: 
     model = MyModel 
     fields = ('id', 'name', 'url',) 
     extra_kwargs = {'id': {'read_only': False, 'required': True}} 

Auf diese Weise konnte ich die richtige Instanz abzurufen und zu aktualisieren, es

+2

und was passiert bei einer 'create' Methode, bei der' id' redundant ist? – dimmg

0

Versuchen

def update(self, instance, validated_data): 
    instance.nr = validated_data.get('nr', instance.nr) 
    instance.title = validated_data.get('title', instance.title) 
    instance.save() 


    items = validated_data.get('items') 
    for item in items: 
     inv_item = InvoiceItem.objects.get(invoice=instance, pk=item.pk) 
     inv_item.name = item.get('name', inv_item.name) 
     inv_item.price = item.get('price', inv_item.price) 
     inv_item.invoice = instance 
     inv_item.save() 

    instance.save() 
    return instance 
Verwandte Themen