外部キー
CoddyのDjangoジャーニー「モデルと管理サイト」セクションの一部。レッスン 16/23。
あなたの本のうち2冊はジェーン・オースティンの作品で、どちらにも彼女の名前が入力されています。誤字を直すには、2か所とも修正しなければなりません。各著者をそれぞれ専用のテーブルに1回だけ登録し、各本から著者を参照するようにしましょう。その参照に使うのがForeignKeyです。友人に貸した本を記録するLoanは、その本を参照します。
class Loan(models.Model):
book = models.ForeignKey(Book, on_delete=models.PROTECT)
friend = models.CharField(max_length=100)
lent_on = models.DateField()カラムには本のidであるbook_idが保存されます。Pythonでは、loan.bookが本そのものを表すBookです。複数の貸出記録から1冊の本を参照できます。これが多対一の関係です。
on_deleteは必須です。これは、本が削除されたときに貸出記録をどうするかを指定します。CASCADEは貸出記録も削除し、PROTECTは本の削除を拒否します。SET_NULLはフィールドを空にしますが、その場合はnull=Trueも必要です。
Authorモデルはすでに用意されており、その__str__は名前を返すので、テンプレート内の{{ book.author }}は引き続き動作します。
チャレンジ
中級books/models.pyで、Book.authorをテキストからAuthorへのリンクに変更します。著者が削除されると、その著者の本も一緒に削除されます。
「実行」を押して「データ」タブを開きます。books.Authorには6人の著者が格納され、本の行にはそれぞれのIDが格納されています。
自分で試してみよう
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}"
モデルと管理サイトのすべてのレッスン
自分で練習してみよう: Djangoプレイグラウンド