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"
}
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 ". –
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
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.) –