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 tes livres sont de Jane Austen, et son nom est saisi dans les deux : corrige une faute de frappe et tu dois la corriger deux fois. Garde chaque auteur une seule fois, dans sa propre table, et fais pointer chaque livre vers son auteur. Ce pointeur est une ForeignKey. Un Loan, c’est un livre que tu as prêté à un ami ; il 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 seul 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 empêche la suppression du livre, et SET_NULL vide le champ, 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 tes modèles.

challenge icon

Défi

Moyen

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

Appuie sur « Jouer » et clique sur Dune : sa page indique toujours by Frank Herbert.

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