2015-06-05 8 views
5

Ho un ItemCollection e articoli nei miei modelli Django e voglio essere in grado di rimuovere elementi dalla collezione attraverso l'interfaccia utente. In una richiesta REST PUT aggiungo un campo booleano extra deleted per ciascun elemento per segnalare che un elemento deve essere eliminato.Impossibile ottenere un campo non modello nel parametro validated_data di un serializzatore Django Rest Framework

Il modo corretto per gestire questo sembra essere nel metodo update del serializzatore. Il mio problema è che questo campo non modello deleted viene rimosso durante la convalida, quindi non è più disponibile. L'aggiunta di deleted come SerializerMethodField non ha aiutato. Per ora ricevo le mie informazioni deleted dall'attributo initial_data del Serializer, ma non mi sembra giusto.

Il mio codice di esempio corrente è di seguito. Qualcuno conosce un approccio migliore?

Modelli:

class ItemCollection(models.Model): 
     description = models.CharField(max_length=256) 


    class Item(models.Model): 
     collection = models.ForeignKey(ItemCollection, related_name="items") 

Serializzatori:

from django.shortcuts import get_object_or_404 
    from rest_framework.views import APIView 
    from rest_framework.response import Response 
    from rest_framework import serializers 
    from models import Item, ItemCollection 


    class ItemSerializer(serializers.ModelSerializer): 

     class Meta: 
      model = Item 


    class ItemCollectionSerializer(serializers.ModelSerializer): 

     items = ItemSerializer(many=True, read_only=False) 

     class Meta: 
      model = ItemCollection 

     def update(self, instance, validated_data): 
      instance.description = validated_data['description'] 
      for item, item_obj in zip(
        self.initial_data['items'], validated_data['items']): 
       if item['delete']: 
        instance.items.filter(id=item['id']).delete() 
      return instance 


    class ItemCollectionView(APIView): 

     def get(self, request, ic_id): 
      item_collection = get_object_or_404(ItemCollection, pk=ic_id) 
      serialized = ItemCollectionSerializer(item_collection).data 
      return Response(serialized) 

     def put(self, request, ic_id): 
      item_collection = get_object_or_404(ItemCollection, pk=ic_id) 
      serializer = ItemCollectionSerializer(
       item_collection, data=request.data) 
      if serializer.is_valid(raise_exception=True): 
       serializer.save() 
      return Response(serializer.data) 

e un esempio della JSON nella richiesta PUT:

{ 
     "id": 2, 
     "items": [ 
      { 
       "id": 3, 
       "collection": 2, 
       "delete": true 
      } 
     ], 
     "description": "mycoll" 
    } 
+0

Sarebbe accettabile eseguire semplicemente un 'DELETE' HTTP separato per ciascuno dei moduli nidificati che devono essere eliminati? Se dovessi usare 'serializers.HyperlinkedModelSerializer' come classe base dei tuoi serializzatori, ogni sotto-voce avrebbe un URL che potresti facilmente" CANCELLARE ". –

+0

Questa è un'angolazione interessante da esplorare. Anche se, il problema principale è che le informazioni su quali elementi devono essere eliminati mancano in 'validated_data'. – jjmurre

+0

Quello che voglio dire è che sul lato client, invece di impostare il flag 'delete' sull'elemento secondario, basta fare un' DELETE' su HTTP per quell'oggetto e rimuoverlo dal contenitore. Non fai il 'DELETE' da dentro Django (se posso presumere che stavi insinuando quell'approccio.) –

risposta

13

è possibile aggiungere campi non-modello indietro sovrascrivendo to_internal_value fn:

Quindi è possibile elaborarlo come desiderato in create o update.