Detailseite eines Genres
Die Detailseite eines Genres soll die Informationen zu einem bestimmten Genre anzeigen. Als Kennung dient der Wert seines automatisch generierten Feldes _id.
Die ID des gewünschten Genre-Datensatzes steht am Ende der URL und wird anhand der Routendefinition (/genre/:id) automatisch extrahiert.
Im Controller ist sie über die Request-Parameter zugänglich: req.params.id.
Die Seite soll den Namen des Genres und eine Liste aller Bücher dieses Genres anzeigen, jeweils mit einem Link zur Detailseite des Buches.
Controller
Öffnen Sie controllers/genreController.js und importieren Sie das Modul Book am Anfang der Datei (das Modul Genre sollte bereits importiert sein).
import Book from "../models/book.js";
Suchen Sie die exportierte Controller-Methode genreDetail() und ersetzen Sie sie durch den folgenden Code.
// Display detail page for a specific Genre.
export const genreDetail = async (req, res, next) => {
// Get details of genre and all associated books (in parallel)
const [genre, booksInGenre] = await Promise.all([
Genre.findById(req.params.id).exec(),
Book.find({ genre: req.params.id }, "title summary").exec(),
]);
if (genre === null) {
// No results.
const err = new Error("Genre not found");
err.status = 404;
return next(err);
}
res.render("genre_detail", {
title: "Genre Detail",
genre,
genre_books: booksInGenre,
});
};
Zunächst verwenden wir Genre.findById(), um die Genre-Informationen für eine bestimmte ID abzurufen, und Book.find(), um alle Buch-Datensätze mit derselben zugehörigen Genre-ID abzurufen.
Da die beiden Abfragen nicht voneinander abhängen, verwenden wir Promise.all(), um sie parallel auszuführen (dieselbe Vorgehensweise wurde bereits auf der Startseite gezeigt).
Wir warten mit await auf die zurückgegebene Promise und prüfen die Ergebnisse, sobald sie erfüllt oder abgelehnt wurde.
Wenn das Genre nicht in der Datenbank vorhanden ist (etwa weil es gelöscht wurde), liefert findById() erfolgreich ein leeres Ergebnis zurück.
In diesem Fall möchten wir eine „Nicht gefunden“-Seite anzeigen. Dazu erstellen wir ein Error-Objekt und übergeben es an die nächste Middleware-Funktion next in der Kette.
Hinweis:
Fehler, die an die Middleware-Funktion next übergeben werden, gelangen zu unserem Code für die Fehlerbehandlung (dieser wurde beim Erstellen des Grundgerüsts der Anwendung eingerichtet). Weitere Informationen finden Sie unter Fehler behandeln und Fehler und Ausnahmen in den Routenfunktionen behandeln.
Wenn das genre gefunden wurde, rufen wir render() auf, um die Ansicht anzuzeigen.
Die Ansichtsvorlage heißt genre_detail (.pug).
Die Werte für den Titel, genre und booksInGenre werden über die entsprechenden Schlüssel (title, genre und genre_books) an die Vorlage übergeben.
Ansicht
Erstellen Sie views/genre_detail.pug und füllen Sie die Datei mit folgendem Inhalt:
extends layout
block content
h1 Genre: #{genre.name}
div(style='margin-left:20px;margin-top:20px')
h2(style='font-size: 1.5rem;') Books
if genre_books.length
dl
each book in genre_books
dt
a(href=book.url) #{book.title}
dd #{book.summary}
else
p This genre has no books.
Die Ansicht ähnelt unseren anderen Vorlagen sehr. Der wichtigste Unterschied besteht darin, dass wir den übergebenen title nicht für die erste Überschrift verwenden (er wird jedoch in der zugrunde liegenden Vorlage layout.pug verwendet, um den Seitentitel festzulegen).
Wie sieht das Ergebnis aus?
Starten Sie die Anwendung und öffnen Sie http://localhost:3000/ in Ihrem Browser. Wählen Sie den Link All genres und anschließend eines der Genres aus (z. B. „Fantasy“). Wenn alles richtig eingerichtet ist, sollte Ihre Seite etwa wie im folgenden Screenshot aussehen.

Hinweis:
Möglicherweise erhalten Sie einen Fehler wie den folgenden, wenn req.params.id (oder eine andere ID) nicht in eine mongoose.Types.ObjectId() umgewandelt werden kann.
Cast to ObjectId failed for value " 59347139895ea23f9430ecbb" at path "_id" for model "Genre"
Die wahrscheinlichste Ursache ist, dass der an die Mongoose-Methoden übergebene Wert keine gültige ID ist.
Mit Mongoose.prototype.isValidObjectId() können Sie prüfen, ob eine bestimmte ID gültig ist.