Menu
CoddyTech

Chiavi esterne

Fa parte della sezione Modelli e pannello di amministrazione del percorso Django di Coddy. Lezione 16 di 23.

Due dei tuoi libri sono di Jane Austen e il suo nome è scritto in entrambi: correggi un refuso e dovrai correggerlo due volte. Conserva ogni autore una sola volta, in una tabella dedicata, e fai in modo che ogni libro rimandi al proprio autore. Questo riferimento è una ForeignKey. Un Loan, cioè un libro che hai prestato a un amico, rimanderebbe al proprio libro:

class Loan(models.Model):
    book = models.ForeignKey(Book, on_delete=models.PROTECT)
    friend = models.CharField(max_length=100)
    lent_on = models.DateField()

La colonna memorizza l'id del libro, book_id; in Python, loan.book è il Book stesso. Molti prestiti possono rimandare a un unico libro: una relazione molti-a-uno.

on_delete è obbligatorio: indica cosa succede ai prestiti quando il loro libro viene eliminato. CASCADE li elimina a sua volta, PROTECT impedisce di eliminare il libro e SET_NULL svuota il campo, che richiede quindi null=True.

Un modello Author è pronto e il suo __str__ restituisce il nome, quindi {{ book.author }} nei tuoi template continua a funzionare.

challenge icon

Sfida

Medio

In books/models.py, modifica Book.author da testo a collegamento a Author. Quando un autore viene eliminato, anche i suoi libri vengono eliminati.

Premi Esegui e apri la scheda Dati: books.Author contiene i sei autori, e le righe dei libri contengono i loro ID.

Provalo tu

from django.db import models


class Author(models.Model):
    name = models.CharField(max_length=100)

    class Meta:
        ordering = ["name"]

    def __str__(self):
        return self.name


class Book(models.Model):
    class Genre(models.TextChoices):
        FICTION = "fiction", "Fiction"
        SCIFI = "scifi", "Science fiction"
        MYSTERY = "mystery", "Mystery"
        HISTORY = "history", "History"

    title = models.CharField(max_length=200)
    author = models.CharField(max_length=100)
    year = models.IntegerField()
    price = models.DecimalField(max_digits=6, decimal_places=2)
    is_read = models.BooleanField(default=False)
    finished = models.DateField(null=True, blank=True)
    summary = models.TextField(blank=True)
    genre = models.CharField(max_length=20, choices=Genre, default=Genre.FICTION)

    class Meta:
        ordering = ["title"]

    def __str__(self):
        return f"{self.title} by {self.author}"

Tutte le lezioni di Modelli e pannello di amministrazione

Esercitati da solo: Playground Django