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.
Défi
MoyenDans 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
3Des pages issues de la base de données
Une liste issue de la base de donnéesUne page pour chaque livreEntraînez-vous par vous-même : Playground Django