Внешние ключи
Часть раздела Модели и панель администратора путешествия по Django на Coddy. Урок 16 из 23.
Две ваши книги написаны Джейн Остин, и её имя указано в обеих: исправьте опечатку — и исправлять придётся дважды. Храните каждого автора один раз в отдельной таблице и связывайте каждую книгу с её автором. Такая связь задаётся с помощью ForeignKey. Объект Loan, представляющий книгу, которую вы одолжили другу, будет ссылаться на эту книгу:
class Loan(models.Model):
book = models.ForeignKey(Book, on_delete=models.PROTECT)
friend = models.CharField(max_length=100)
lent_on = models.DateField()В столбце хранится идентификатор книги — book_id; в Python loan.book — это сама Book. На одну книгу может ссылаться много займов: это связь «многие к одному».
on_delete обязателен: он определяет, что произойдёт с займами при удалении связанной книги. CASCADE удаляет их тоже, PROTECT запрещает удалять книгу, а SET_NULL очищает поле; для этого требуется null=True.
Модель Author уже готова, а её метод __str__ возвращает имя, поэтому {{ book.author }} в шаблонах продолжит работать.
Задание
СреднеВ books/models.py измени Book.author: вместо текстового поля сделай ссылку на Author. При удалении автора его книги удаляются вместе с ним.
Нажми «Run» и открой вкладку «Data»: в books.Author хранятся шесть авторов, а строки с книгами содержат их идентификаторы.
Попробуйте сами
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