型別詳情頁
型別詳情頁需要使用其自動生成的 _id 欄位值作為識別符號來顯示特定型別例項的資訊。所需型別記錄的 ID 編碼在 URL 的末尾,並根據路由定義(/genre/:id)自動提取。然後在控制器中透過請求引數 req.params.id 訪問它。
頁面應顯示型別名稱以及該型別下所有圖書的列表,幷包含指向每本圖書詳情頁的連結。
控制器
開啟 /controllers/genreController.js 並在檔案頂部引入 Book 模組(檔案應該已經 require() 了 Genre 模組)。
const Book = require("../models/book");
找到匯出的 genre_detail() 控制器方法,並用以下程式碼替換它。
// Display detail page for a specific Genre.
exports.genre_detail = 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,
});
};
我們首先使用 Genre.findById() 獲取特定 ID 的型別資訊,並使用 Book.find() 獲取所有具有相同關聯型別 ID 的圖書記錄。由於兩個請求不互相依賴,我們使用 Promise.all() 並行執行資料庫查詢(在 主頁 中演示了並行查詢的相同方法)。
我們 await 返回的 promise,一旦它得到解決,我們就檢查結果。如果資料庫中不存在該型別(即可能已被刪除),那麼 findById() 將成功返回但沒有結果。在這種情況下,我們希望顯示一個“未找到”頁面,因此我們建立一個 Error 物件並將其傳遞給鏈中的 next 中介軟體函式。
注意: 傳遞給 next 中介軟體函式的錯誤會傳播到我們的錯誤處理程式碼(這是在我們 生成應用骨架 時設定的)。有關更多資訊,請參閱 處理錯誤 和 處理路由函式中的錯誤和異常)。
如果找到 genre,則呼叫 render() 來顯示檢視。檢視模板是 genre_detail (.pug)。標題、genre 和 booksInGenre 的值透過對應的鍵(title、genre 和 genre_books)傳遞到模板中。
檢視
建立 /views/genre_detail.pug 並用以下文字填充它
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.
該檢視與我們所有其他模板非常相似。主要區別在於,我們不使用傳遞的 title 作為第一個標題(儘管它在底層的 layout.pug 模板中用於設定頁面標題)。
它看起來怎麼樣?
執行應用程式,然後在瀏覽器中開啟 https://:3000/。選擇“所有型別”連結,然後選擇其中一個型別(例如,“奇幻”)。如果一切設定正確,您的頁面應該看起來像下面的截圖。

注意: 如果 req.params.id(或任何其他 ID)無法強制轉換為 mongoose.Types.ObjectId(),您可能會遇到與下方類似的錯誤。
Cast to ObjectId failed for value " 59347139895ea23f9430ecbb" at path "_id" for model "Genre"
最可能的原因是傳遞給 mongoose 方法的 ID 實際上不是一個 ID。可以使用 Mongoose.prototype.isValidObjectId() 來檢查特定 ID 是否有效。
後續步驟
- 返回 Express 教程第 5 部分:顯示圖書館資料。
- 繼續第 5 部分的下一篇文章:圖書詳情頁。