00
:
00
:
00
:
00
•Corso SEO AI - Usa SEOEMAIL al checkout per il 30% di sconto

Serializer

I Serializer in Django REST Framework (DRF) sono responsabili della conversione dei dati complessi, come istanze di modelli Django e queryset, in tipi di dati Python nativi che possono essere facilmente renderizzati in JSON o altri formati. Gestiscono anche la deserializzazione, ovvero la validazione e la conversione dei dati in ingresso.

La Classe Serializer

La classe base Serializer permette di definire manualmente i campi e la logica di serializzazione.

from rest_framework import serializers

class LibroSerializer(serializers.Serializer):
    id = serializers.IntegerField(read_only=True)
    titolo = serializers.CharField(max_length=200)
    autore = serializers.CharField(max_length=100)
    prezzo = serializers.DecimalField(max_digits=6, decimal_places=2)
    pubblicato = serializers.BooleanField(default=False)

    def create(self, validated_data):
        return Libro.objects.create(**validated_data)

    def update(self, instance, validated_data):
        instance.titolo = validated_data.get('titolo', instance.titolo)
        instance.autore = validated_data.get('autore', instance.autore)
        instance.prezzo = validated_data.get('prezzo', instance.prezzo)
        instance.pubblicato = validated_data.get('pubblicato', instance.pubblicato)
        instance.save()
        return instance

ModelSerializer

ModelSerializer genera automaticamente i campi del serializer a partire da un modello Django, riducendo significativamente il codice da scrivere.

from rest_framework import serializers
from .models import Libro

class LibroSerializer(serializers.ModelSerializer):
    class Meta:
        model = Libro
        fields = ['id', 'titolo', 'autore', 'prezzo', 'pubblicato']
        # oppure tutti i campi:
        # fields = '__all__'
        # oppure escludi specifici campi:
        # exclude = ['data_creazione']

ModelSerializer genera automaticamente i metodi create() e update(), i validatori basati sui vincoli del modello e i campi corrispondenti ai campi del modello.

Tipi di Campo Comuni

DRF offre numerosi tipi di campo per la serializzazione:

class ProdottoSerializer(serializers.ModelSerializer):
    # Campi personalizzati aggiuntivi
    nome = serializers.CharField(max_length=200)
    descrizione = serializers.CharField(allow_blank=True)
    prezzo = serializers.DecimalField(max_digits=10, decimal_places=2)
    disponibile = serializers.BooleanField(default=True)
    quantita = serializers.IntegerField(min_value=0)
    data_aggiunta = serializers.DateTimeField(read_only=True)
    immagine_url = serializers.URLField(required=False)
    categoria = serializers.ChoiceField(choices=['elettronica', 'libri', 'abbigliamento'])

    class Meta:
        model = Prodotto
        fields = '__all__'

Campi read_only e write_only

I campi possono essere configurati come sola lettura o sola scrittura per controllare il flusso dei dati.

class UtenteSerializer(serializers.ModelSerializer):
    password = serializers.CharField(write_only=True, min_length=8)
    data_registrazione = serializers.DateTimeField(read_only=True)

    class Meta:
        model = Utente
        fields = ['id', 'username', 'email', 'password', 'data_registrazione']
        read_only_fields = ['id', 'data_registrazione']

    def create(self, validated_data):
        utente = Utente.objects.create_user(**validated_data)
        return utente

I campi read_only vengono inclusi nella risposta ma ignorati durante la deserializzazione. I campi write_only vengono accettati in input ma non inclusi nella risposta (ideali per le password).

Validazione

DRF offre diversi livelli di validazione: a livello di campo, a livello di oggetto e tramite validatori personalizzati.

class OrdineSerializer(serializers.ModelSerializer):
    class Meta:
        model = Ordine
        fields = ['id', 'prodotto', 'quantita', 'indirizzo']

    # Validazione a livello di singolo campo
    def validate_quantita(self, value):
        if value <= 0:
            raise serializers.ValidationError("La quantita deve essere positiva.")
        if value > 100:
            raise serializers.ValidationError("Non puoi ordinare piu di 100 pezzi.")
        return value

    # Validazione a livello di oggetto (campi multipli)
    def validate(self, data):
        if data.get('quantita', 0) > 10 and not data.get('indirizzo'):
            raise serializers.ValidationError(
                "Per ordini superiori a 10 pezzi, l'indirizzo e' obbligatorio."
            )
        return data

SerializerMethodField

SerializerMethodField permette di aggiungere campi calcolati al serializer, il cui valore viene determinato da un metodo personalizzato.

class LibroSerializer(serializers.ModelSerializer):
    prezzo_scontato = serializers.SerializerMethodField()
    nome_completo_autore = serializers.SerializerMethodField()

    class Meta:
        model = Libro
        fields = ['id', 'titolo', 'prezzo', 'prezzo_scontato', 'nome_completo_autore']

    def get_prezzo_scontato(self, obj):
        return round(obj.prezzo * 0.9, 2)

    def get_nome_completo_autore(self, obj):
        return f"{obj.autore.nome} {obj.autore.cognome}"

Il metodo associato deve seguire la convenzione get_<nome_campo> e riceve l’istanza dell’oggetto come argomento.

Serializer Annidati

I serializer possono essere annidati per rappresentare relazioni tra modelli.

class AutoreSerializer(serializers.ModelSerializer):
    class Meta:
        model = Autore
        fields = ['id', 'nome', 'cognome']


class LibroSerializer(serializers.ModelSerializer):
    autore = AutoreSerializer(read_only=True)
    autore_id = serializers.PrimaryKeyRelatedField(
        queryset=Autore.objects.all(),
        source='autore',
        write_only=True
    )

    class Meta:
        model = Libro
        fields = ['id', 'titolo', 'autore', 'autore_id', 'prezzo']

Con questa struttura, la risposta GET include i dettagli completi dell’autore, mentre per creare un libro basta inviare l’autore_id.

I Metodi create() e update()

Personalizzare create() e update() permette di gestire logiche complesse durante il salvataggio.

class ProfiloSerializer(serializers.ModelSerializer):
    competenze = serializers.ListField(child=serializers.CharField())

    class Meta:
        model = Profilo
        fields = ['id', 'bio', 'competenze']

    def create(self, validated_data):
        competenze = validated_data.pop('competenze', [])
        profilo = Profilo.objects.create(**validated_data)
        for comp in competenze:
            Competenza.objects.create(profilo=profilo, nome=comp)
        return profilo

    def update(self, instance, validated_data):
        competenze = validated_data.pop('competenze', None)
        instance.bio = validated_data.get('bio', instance.bio)
        instance.save()
        if competenze is not None:
            instance.competenze.all().delete()
            for comp in competenze:
                Competenza.objects.create(profilo=instance, nome=comp)
        return instance

Conclusione

I Serializer sono il cuore di Django REST Framework e svolgono un ruolo fondamentale nella trasformazione e validazione dei dati. Dalla classe base Serializer al piu’ pratico ModelSerializer, passando per la validazione a piu’ livelli, i campi calcolati con SerializerMethodField e i serializer annidati, padroneggiare questi strumenti e’ essenziale per costruire API robuste e ben strutturate.