Menu
CoddyTech

Chaves estrangeiras

Parte da seção Models e o Admin do Journey de Django da Coddy. Lição 16 de 23.

Dois dos seus livros são de Jane Austen, e o nome dela está digitado nos dois: corrija um erro de digitação e você terá que corrigi-lo duas vezes. Mantenha cada autora uma única vez, em uma tabela própria, e faça cada livro apontar para sua autora. Esse ponteiro é uma ForeignKey. Um Loan, um livro que você emprestou a um amigo, apontaria para o livro:

class Loan(models.Model):
    book = models.ForeignKey(Book, on_delete=models.PROTECT)
    friend = models.CharField(max_length=100)
    lent_on = models.DateField()

A coluna armazena o id do livro, book_id; em Python, loan.book é o próprio Book. Muitos empréstimos podem apontar para um livro: uma relação muitos para um.

on_delete é obrigatório: ele determina o que acontece com os empréstimos quando o livro é excluído. CASCADE também os exclui, PROTECT impede a exclusão do livro, e SET_NULL esvazia o campo, que então precisa de null=True.

Um modelo Author está pronto, e seu __str__ é o nome, então {{ book.author }} continua funcionando nos seus templates.

challenge icon

Desafio

Médio

Em books/models.py, altere Book.author de texto para um link para Author. Quando um autor for excluído, seus livros também serão excluídos.

Pressione Run e abra a aba Data: books.Author contém os seis autores, e as linhas dos livros contêm os IDs deles.

Experimente você mesmo

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}"

Todas as lições de Models e o Admin

Pratique por conta própria: Playground de Django