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 zweimal beheben. Führe jeden Autor nur einmal in einer eigenen Tabelle 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 Buches, 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 Buches, 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 zu einem Verweis auf Author. Wenn ein Autor gelöscht wird, werden auch seine Bücher gelöscht.

Klicke auf „Spielen“ und dann auf Dune: Auf der Seite steht weiterhin von Frank Herbert.

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