Я следовал руководству на сайте MDN для Node / express / mongoose.Это может быть знакомо многим, но я все равно опишу код.Я хочу создать представление, похожее на страницу book_list, однако мне бы хотелось иметь возможность отправлять экземпляры книги с каждой книгой (подробности будут приведены ниже).Другими словами, я хотел бы иметь возможность иметь BookInstances для каждой книги как часть объекта книги на странице списка - это в основном для подсчета (или длины), но я могу также использовать его другими способами.
Модель книги
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var BookSchema = new Schema({
title: {type: String, required: true},
author: { type: Schema.ObjectId, ref: 'Author', required: true },
summary: {type: String, required: true},
isbn: {type: String, required: true},
genre: [{ type: Schema.ObjectId, ref: 'Genre' }]
});
// Virtual for this book instance URL.
BookSchema
.virtual('url')
.get(function () {
return '/catalog/book/'+this._id;
});
// Export model.
module.exports = mongoose.model('Book', BookSchema);
Часть схемы BookInstance модели:
var BookInstanceSchema = new Schema(
{
book: { type: Schema.Types.ObjectId, ref: 'Book', required: true },//reference to the associated book
imprint: { type: String, required: true },
status: { type: String, required: true, enum: ['Available', 'Maintenance', 'Loaned', 'Reserved'], default: 'Maintenance' },
due_back: { type: Date, default: Date.now }
}
);
Контроллер списка книг:
// Display list of all Books.
exports.book_list = function(req, res, next) {
Book.find({}, 'title author')
.populate('author')
.exec(function (err, list_books) {
if (err) { return next(err); }
//Successful, so render
res.render('book_list', { title: 'Book List', book_list: list_books });
});
};
Контроллер детализации книги:
// Display detail page for a specific book.
exports.book_detail = function(req, res, next) {
async.parallel({
book: function(callback) {
Book.findById(req.params.id)
.populate('author')
.populate('genre')
.exec(callback);
},
book_instance: function(callback) {
BookInstance.find({ 'book': req.params.id })
.exec(callback);
},
}, function(err, results) {
if (err) { return next(err); }
if (results.book==null) { // No results.
var err = new Error('Book not found');
err.status = 404;
return next(err);
}
// Successful, so render.
res.render('book_detail', { title: 'Book Detail', book: results.book,
book_instances: results.book_instance } );
});
};
У меня такое чувство, что это может быть что-то, что можно сделать с помощью заполнить , но у меня не получается, чтобы это работало.Единственный способ, которым мне удалось заставить объект экземпляра книги отображаться в списке для каждого элемента книги, - это отправить все экземпляры книги в представление.Оттуда я использую цикл foreach , а затем оператор IF , чтобы получить экземпляры книги для каждой книги.Это выглядит ужасно, и я уверен, что должен быть какой-то другой способ сделать это.Я привык к asp.net mvc - в этом вы используете виртуальный объект.Я не уверен, если я должен изменить модель здесь или контроллер.Возможно, я также захочу передать гораздо более сложную модель со списками в списках.
Я заметил, что жанр фактически сохраняется в документе книги в отличие от bookinstances - отсюда и строки в контроллере деталей книги:
book_instance: function(callback) {
BookInstance.find({ 'book': req.params.id })
.exec(callback);
},
Ниже я показал, что я сделал.Я мог бы также сделать это как объекты в контроллере, но теперь у меня есть следующее:
Контроллер книг:
exports.book_list = function (req, res, next) {
async.parallel({
books: function (callback) {
Book.find()
.exec(callback)
},
bookinstances: function (callback) {
BookInstance.find()
.exec(callback)
},
}, function (err, results) {
if (err) { return next(err); } // Error in API usage.
// Successful, so render.
res.render('book_list', { title: 'Book Detail', books: results.books,
bookinstances: results.bookinstances });
});
};
Код book_list.pug:
extends layout
block content
h1= title
table.table
th Book
th BookInstance Count
th
//- above th is for buttons only (no title)
each book in books
- var instCount = 0
each bookinstance in bookinstances
if book._id.toString() === bookinstance.book.toString()
- instCount++
tr
td
a(href=book.url) #{book.title}
td #{instCount}
td
a.btn.btn-sm.btn-primary(href=book.url+'/update') Update
if !instCount
a.btn.btn-sm.btn-danger(href=book.url+'/delete') Delete
else
li There are no books.
Как выглядит страница: