Menu
CoddyTech

Claves foráneas

Parte de la sección Modelos y el panel de administración del Journey de Django de Coddy. Lección 16 de 23.

Dos de tus libros son de Jane Austen, y su nombre está escrito en ambos: corriges un error tipográfico y lo corriges dos veces. Guarda cada autor una sola vez, en su propia tabla, y haz que cada libro apunte a su autor. Ese puntero es una ForeignKey. Un Loan, un libro que le prestaste a un amigo, apuntaría a su libro:

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

La columna almacena el id del libro, book_id; en Python, loan.book es el propio Book. Muchos préstamos pueden apuntar a un mismo libro: una relación de muchos a uno.

on_delete es obligatorio: indica qué ocurre con los préstamos cuando se elimina su libro. CASCADE también los elimina, PROTECT impide eliminar el libro y SET_NULL vacía el campo, lo que requiere null=True.

El modelo Author está listo y su __str__ es el nombre, así que {{ book.author }} sigue funcionando en tus plantillas.

challenge icon

Desafío

Intermedio

En books/models.py, cambia Book.author de texto a un enlace a Author. Cuando se elimina un autor, sus libros se eliminan con él.

Pulsa Run y abre la pestaña Data: books.Author contiene los seis autores, y las filas de libros contienen sus identificadores.

Pruébalo tú mismo

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 las lecciones de Modelos y el panel de administración

Practica por tu cuenta: Playground de Django