Modelli in Django

Completato

I modelli costituiscono il fulcro di qualsiasi ORM. Un modello è una rappresentazione di alcuni dati con cui verrà usata l'applicazione. Può trattarsi di una persona, un prodotto, una categoria o qualsiasi altra tipologia di dati necessaria per l'applicazione.

Creazione di un modello

In Django un modello è qualsiasi classe che eredita una raccolta di funzionalità da django.models.Model. La raccolta include metodi che consentono di eseguire query sul database, creare nuove voci e salvare gli aggiornamenti. È anche possibile definire campi, impostare metadati e stabilire relazioni tra modelli.

Se si vogliono creare due modelli, Product e Category, è necessario aggiungere due classi:

from django.db import models
class Product(models.Model):
    # details would go here
    pass

class Category(models.Model):
    # details would go here
    pass

Aggiungere metodi

Prima di illustrare come configurare i dati per il modello, è importante evidenziare il fatto che un modello è una classe Python. Di conseguenza, è possibile sia aggiungere metodi sia eseguire l'override di quelli forniti daDjango.models.Model o di quelli inerenti a tutti gli oggetti Python.

Un metodo da evidenziare in particolare è __str__. Questo metodo consente di visualizzare un oggetto se non è specificato alcun campo. Se Product contiene un campo name (che verrà visualizzato tra poco), è possibile restituirlo come rappresentazione di stringa predefinita per Product eseguendo l'override di __str__.

class Product(models.Model):
    name = models.TextField()
    
    def __str__(self):
        return self.name

Aggiungi campi

I campi definiscono la struttura dei dati di un modello. I campi possono includere il nome di un elemento, una data di creazione, un prezzo o qualsiasi altro elemento che deve essere archiviato dal modello.

Elementi diversi hanno tipi di dati, regole di convalida e altre forme di metadati differenti. L'ORM di Django contiene una vasta gamma di opzioni per configurare i campi dei modelli in base alle specifiche desiderate. L'ORM è estendibile ed è quindi possibile creare regole personalizzate in base alle esigenze.

Definizione del tipo di campo

L'elemento principale dei metadati di tutti i campi è il tipo di dati che verrà archiviato, ad esempio una stringa o un numero. Il mapping dei tipi di campo viene eseguito a un tipo di database e a un tipo di controllo del modulo HTML, ad esempio una casella di testo o una casella di controllo. Django include diversi tipi di campi, tra cui:

  • CharField: riga di testo singola.
  • TextField: più righe di testo.
  • BooleanField: opzione booleana true/false.
  • DateField: data.
  • TimeField: ora.
  • DateTimeField: data e ora.
  • URLField: URL.
  • IntegerField: numero intero.
  • DecimalField: numero decimale a precisione fissa.

Per aggiungere campi alle classi Product e Category, è possibile usare il codice seguente:

from django.db import models
class Product(models.Model):
    name = models.TextField()
    price = models.DecimalField()
    creation_date = models.DateField()

class Category(models.Model):
    name = models.TextField()

Opzioni di campo

È possibile usare le opzioni di campo per aggiungere metadati per ammettere valori Null o vuoti o per contrassegnare un campo come univoco. È anche possibile impostare le opzioni di convalida e fornire messaggi personalizzati per gli errori di convalida.

Analogamente ai tipi di campo, le opzioni di campo vengono associate alle impostazioni appropriate nel database. Le regole verranno applicate in tutti i moduli generati da Django per conto dell'utente.

Le opzioni di campo vengono passate nella funzione per il campo stesso. Campi diversi potrebbero supportare opzioni diverse. Ecco alcune delle opzioni più comuni:

  • null
    • Opzione booleana per consentire valori Null.
    • Il valore predefinito è False.
  • blank
    • Opzione booleana per consentire valori vuoti.
    • Il valore predefinito è False.
  • default
    • Consente la configurazione di un valore predefinito se non è specificato un valore per il campo.
    • Se si vuole impostare il valore predefinito su un database null, impostare default su None.
  • unique
    • Questo campo deve contenere un valore univoco.
    • Il valore predefinito è False.
  • min_length e max_length
    • Usati con i tipi stringa per identificare la lunghezza minima e massima della stringa.
    • Il valore predefinito è None.
  • min_value e max_value
    • Usati con i tipi numero per identificare i valori minimo e massimo.
  • auto_now e auto_now_add.
    • Usati con i tipi data/ora per indicare se deve essere usata l'ora corrente.
    • auto_now imposta sempre il campo sull'ora corrente al momento del salvataggio, informazione utile per i campi last_update.
    • auto_now_add imposta il campo sull'ora corrente al momento della creazione, informazione utile per i campi creation_date.

Nota

I valori null e blank possono sembrare simili, ma hanno un significato diverso nella terminologia dei database. null indica un valore mancante, mentre blank è specificamente un valore vuoto.

Per aggiungere opzioni ai modelli, il codice può essere simile al seguente:

from django.db import models
class Product(models.Model):
    name = models.TextField(max_length=50, min_length=3, unique=True)
    price = models.DecimalField(min_value=0.99, max_value=1000)
    creation_date = models.DateField(auto_now_add=True)

class Category(models.Model):
    name = models.TextField(max_length=50, min_length=3, unique=True)

Chiavi e relazioni

Una pratica standard nei database relazionali prevede che ogni riga di una tabella contenga una chiave primaria, in genere un intero incrementato automaticamente. L'ORM di Django aggiunge questa chiave automaticamente a ogni modello creato aggiungendo un campo denominato id.

Se si vuole eseguire l'override di questo comportamento, è possibile impostare il campo da usare come chiave primaria. Tuttavia, nella maggior parte dei casi è consigliabile basarsi sul campo id di Django.

I database relazionali contengono anche relazioni tra tabelle. Un prodotto ha una categoria, un dipendente ha un responsabile e un'auto ha un produttore. L'ORM di Django supporta tutte le relazioni che lo sviluppatore potrebbe voler creare tra i modelli.

La relazione più comune è "uno-a-molti", conosciuta in gergo tecnico come relazione di chiave esterna. In una relazione di chiave esterna più elementi condividono un unico attributo, ad esempio più prodotti vengono raggruppati in un'unica categoria. Per modellare questa relazione, è necessario usare il campo ForeignKey.

Per creare la relazione, aggiungere il campo ForeignKey all'oggetto figlio. Se i prodotti sono raggruppati in categorie, aggiungere la proprietà category alla classe Product e impostare il tipo su ForeignKey.

Django aggiunge automaticamente una proprietà all'elemento padre per fornire l'accesso a tutti gli elementi figlio denominati <child>_set, dove <child> è il nome dell'oggetto figlio. Nell'esempio illustrato, a Category verrà aggiunto automaticamente product_set per fornire l'accesso a tutti i prodotti inclusi nella categoria.

ForeignKey ha un parametro obbligatorio, on_delete. Questo parametro indica a Django quale operazione eseguire in caso di eliminazione dell'elemento padre. In altre parole, se si elimina una categoria, cosa deve accadere ai prodotti della categoria?

Ecco le due opzioni più comuni:

  • CASCADE, che elimina tutti i prodotti se una categoria nell'esempio viene eliminata.
  • PROTECT, che restituisce un errore se si cerca di eliminare una categoria contenente prodotti.

Nota

Nella maggior parte dei casi è opportuno usare PROTECT.

Per aggiornare il modello in modo da creare la relazione, è possibile usare il codice seguente:

from django.db import models
class Product(models.Model):
    name = models.TextField()
    price = models.DecimalField()
    creation_date = models.DateField()
    category = models.ForeignKey(
        'Category', #The name of the model
        on_delete=models.PROTECT
    )

class Category(models.Model):
    name = models.TextField()
    # product_set will be automatically created