Menu
CoddyTech

外键

本课属于 Coddy Django 学习旅程的“模型和管理后台”单元。第 16 课,共 23 课。

你的两本书都是 Jane Austen 写的,而且两本书都填写了她的名字:改正一个拼写错误,就得改两次。把每位作者只记录一次,分别放在自己的表中,并让每本书指向它的作者。这个指针就是 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 对象本身。多笔借阅可以指向同一本书:这是一种多对一关系。

on_delete 是必需的:它规定删除书籍时,相关借阅会发生什么。CASCADE 会一并删除它们,PROTECT 会阻止删除书籍,而 SET_NULL 会清空该字段,此时还需要设置 null=True。

Author 模型已经准备好了,它的 __str__ 会返回作者姓名,因此模板中的 {{ book.author }} 仍然可以正常使用。

challenge icon

挑战

中等

在 books/models.py 中,将 Book.author 从文本改为指向 Author 的链接。删除作者时,与该作者关联的书也会一并删除。

点击“运行”,再点击 Dune:它的页面仍会显示作者是 Frank Herbert。

亲手试试

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 在线编辑器