Menu
CoddyTech

Clés étrangères

Fait partie de la section Modèles et interface d’administration du Journey Django de Coddy. Leçon 16 sur 23.

Deux de vos livres sont de Jane Austen, et son nom est saisi dans les deux : corrigez une faute de frappe et vous devez la corriger deux fois. Conservez chaque auteur une seule fois, dans sa propre table, et faites pointer chaque livre vers son auteur. Ce pointeur est une ForeignKey. Un Loan, c’est-à-dire un livre que vous avez prêté à un ami, pointerait vers son livre :

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

La colonne stocke l’identifiant du livre, book_id ; en Python, loan.book est le Book lui-même. Plusieurs prêts peuvent pointer vers un même livre : une relation plusieurs-à-un.

on_delete est obligatoire : il indique ce qui arrive aux prêts lorsque leur livre est supprimé. CASCADE les supprime également, PROTECT refuse la suppression du livre, et SET_NULL vide le champ, ce qui nécessite alors null=True.

Un modèle Author est prêt, et son __str__ correspond au nom, donc {{ book.author }} continue de fonctionner dans vos modèles.

challenge icon

Défi

Moyen

Dans books/models.py, remplace Book.author par un lien vers Author au lieu d’un texte. Lorsqu’un auteur est supprimé, ses livres sont également supprimés.

Clique sur Exécuter, puis ouvre l’onglet Données : books.Author contient les six auteurs, et les lignes de livres contiennent leurs identifiants.

Essayez vous-même

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}"

Toutes les leçons de Modèles et interface d’administration

Entraînez-vous par vous-même : Playground Django