Menu
CoddyTech

Fremdschlüssel

Teil des Abschnitts Modelle und Admin-Bereich der Django-Journey von Coddy. Lektion 16 von 23.

Zwei deiner Bücher sind von Jane Austen, und ihr Name steht bei beiden: Behebst du einen Tippfehler, musst du ihn also zweimal beheben. Führe jeden Autor nur einmal in einer eigenen Tabelle auf und lass jedes Buch auf seinen Autor verweisen. Dieser Verweis ist ein ForeignKey. Ein Loan, also ein Buch, das du einem Freund geliehen hast, würde auf sein Buch verweisen:

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

Die Spalte speichert die ID des Buchs, book_id; in Python ist loan.book das Book selbst. Viele Ausleihen können auf ein Buch verweisen: eine Viele-zu-eins-Beziehung.

on_delete ist erforderlich: Es legt fest, was mit den Ausleihen geschieht, wenn ihr Buch gelöscht wird. CASCADE löscht sie ebenfalls, PROTECT verhindert das Löschen des Buchs und SET_NULL leert das Feld, wofür dann null=True erforderlich ist.

Ein Author-Modell ist bereit, und sein __str__ ist der Name, sodass {{ book.author }} in deinen Templates weiterhin funktioniert.

challenge icon

Aufgabe

Mittel

Ändere in books/models.py Book.author von Text in einen Verweis auf Author. Wenn ein Autor gelöscht wird, werden seine Bücher ebenfalls gelöscht.

Klicke auf „Run“ und öffne den Tab „Data“: books.Author enthält die sechs Autoren, und die Buchzeilen enthalten ihre IDs.

Probier es selbst

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

Alle Lektionen in Modelle und Admin-Bereich

Übe selbstständig: Django-Playground