In primo luogo, vuoi supportare la creazione di nuove istanze di libri o solo l'aggiornamento di quelle esistenti?
Se sempre e solo voluto creare nuove istanze del libro che si potrebbe fare qualcosa di simile ...
class PageSerializer(serializers.Serializer):
text = serializers.CharField(max_length=500)
class BookSerializer(serializers.Serializer):
page = PageSerializer(many=True)
title = serializers.CharField(max_length=50)
def create(self, validated_data):
# Create the book instance
book = Book.objects.create(title=validated_data['title'])
# Create or update each page instance
for item in validated_data['pages']:
page = Page(id=item['page_id'], text=item['text'], book=book)
page.save()
return book
Nota che io non ho incluso la book_id
qui. Quando creiamo istanze di libri, non includeremo l'id di un libro. Quando aggiorniamo le istanze di libri, in genere includiamo l'id libro come parte dell'URL, piuttosto che nei dati della richiesta.
Se si desidera supportare sia la creazione e l'aggiornamento delle istanze del libro, è necessario pensare a come si desidera gestire le pagine non incluse nella richiesta, ma sono attualmente associate all'istanza del libro.
È possibile scegliere di ignorare automaticamente tali pagine e lasciarle così come sono, è possibile che si desideri sollevare un errore di convalida o che si desideri eliminarle.
Supponiamo che vogliate cancellare qualsiasi pagina non inclusa nella richiesta.
def create(self, validated_data):
# As before.
...
def update(self, instance, validated_data):
# Update the book instance
instance.title = validated_data['title']
instance.save()
# Delete any pages not included in the request
page_ids = [item['page_id'] for item in validated_data['pages']]
for page in instance.books:
if page.id not in page_ids:
page.delete()
# Create or update page instances that are in the request
for item in validated_data['pages']:
page = Page(id=item['page_id'], text=item['text'], book=instance)
page.save()
return instance
E 'anche possibile che si potrebbe desiderare di solo aggiornamenti supporto del libro, e non sostenere la creazione, nel qual caso, solo includono il metodo update()
.
Esistono vari modi per ridurre il numero di query, ad es. utilizzando la creazione/eliminazione di massa, ma quanto sopra farebbe il lavoro in un modo abbastanza semplice.
Come potete vedere ci sono sottigliezze nei tipi di comportamento che potreste desiderare quando si tratta di dati annidati, quindi pensate attentamente esattamente a quale comportamento vi aspettate in vari casi.
Si noti inoltre che ho utilizzato Serializer
nell'esempio sopra anziché ModelSerializer
. In questo caso è più semplice includere tutti i campi nella classe serializzatore esplicitamente, piuttosto che fare affidamento sull'insieme automatico di campi che lo standard ModelSerializer
genera automaticamente.
'potresti voler supportare solo gli aggiornamenti dei libri ..., includere solo il metodo update()'. In questo caso, come il 'instance' nel metodo di aggiornamento sarà riempito con un libro esistente? – norbertpy
Istanziando il serializzatore con l'argomento della parola chiave 'instance'. Normalmente lo otterresti eseguendo una ricerca basata su una chiave primaria nell'URL. Se stai utilizzando le visualizzazioni generiche che verranno gestite per te. Dai un'occhiata a DetailMixin in 'mixins.py' per l'implementazione di questo. –
Grazie Tom. Ho capito ora. – norbertpy