Menu
CoddyTech

外部キー

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 }}は引き続き動作します。

challenge icon

チャレンジ

中級

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プレイグラウンド