Перевод не завершен. Пожалуйста, помогите перевести эту статью с английского.

Первой создаваемой страницей будет домашняя  страница веб-сайта, доступная из корня сайта ('/') или из каталога (catalog/). На странице будет виден статический текст, описывающий сайт, и динамически вычисляемые "количества" записей разных типов имеющихся в БД.

Маршрут для домашней страницы уже создан. Для завершения страницы обновить функции контроллера, чтобы он извлекал количество записей из БД, и создавал представление (шаблон), который можно использовать для презентации страницы.

Маршрут

Маршруты индексной страницы созданы ранее в предыдущем разделе (previous tutorial). Напомним, все функции маршрутов определены в файле /routes/catalog.js:

// GET catalog home page.
router.get('/', book_controller.index);  //This actually maps to /catalog/ because we import the route with a /catalog prefix

Параметр callback-функции определен в /controllers/bookController.js:

exports.index = function(req, res, next) {   
    res.send('NOT IMPLEMENTED: Site Home Page');
}

Именно эту функцию контроллера мы расширим, чтобы получать информацию из моделей и затем отображать ее, используя шаблоны (представления).

Контроллер

Функция контроллера индекса должна получать информацию о том, сколько книг (Book), экземпляров книг (BookInstance), сколько из них доступно, сколько авторов (Author), жанров (Genre) имеется в БД, должна поместить эту информацию в шаблон, чтобы создать  HTML-страницу, после чего вернуть ее в  HTTP-ответе.

Заметка: Количество экземпляров в каждой модели вычисляется при помощи метода countDocuments() . Он вызывается для модели с возможным набором условий, необходимых для проверки соответствия первому аргументу и callback-функции второго аргумента (обсуждалось ранее в "Использование базы данных с Mongoose" Using a Database (with Mongoose)), причем можно вернуть также запрос Query, а затем выполнить его позже при помощи callback. Эта  callback-функция будет выполняться, когда БД вернет количество записей.  Значение ошибки (or null) будет первым параметром, а количество записей (или null, если была ошибка) -  вторым параметром.

SomeModel.countDocuments({ a_model_field: 'match_value' }, function (err, count) {
 // ... do something if there is an err
 // ... do something with the count if there was no error
 });

Откройте файл /controllers/bookController.js. Почти в самом начале вы должны увидеть экспортируемую функцию index() .

var Book = require('../models/book')

exports.index = function(req, res, next) {
 res.send('NOT IMPLEMENTED: Site Home Page'); 
}

Замените весь код, показанный выше, на следующий фрагмент кода. Первое, что он делает - импортирует (require())  все модели (выделено жирным).  Это требуется, поскольку они нужны для подсчета числа записей. Затем импортируется модуль async .

var Book = require('../models/book');
var Author = require('../models/author');
var Genre = require('../models/genre');
var BookInstance = require('../models/bookinstance');

var async = require('async');

exports.index = function(req, res) {   
    
    async.parallel({
        book_count: function(callback) {
            Book.countDocuments({}, callback); // Pass an empty object as match condition to find all documents of this collection
        },
        book_instance_count: function(callback) {
            BookInstance.countDocuments({}, callback);
        },
        book_instance_available_count: function(callback) {
            BookInstance.countDocuments({status:'Available'}, callback);
        },
        author_count: function(callback) {
            Author.countDocuments({}, callback);
        },
        genre_count: function(callback) {
            Genre.countDocuments({}, callback);
        }
    }, function(err, results) {
        res.render('index', { title: 'Local Library Home', error: err, data: results });
    });
};

Метод async.parallel() передает объект с функциями для получения количества элементов каждой модели. Все эти функции стартуют одновременно. Когда все они завершатся,  будет вызвана финальная callback-функция, в итоговом параметре которой содержится нужный нам результат (или ошибка).

При успешном завершении callback-функции она вызывает res.render(), у которой в качестве параметров - представление (шаблон)  'index' и объект, содержащий данные, которые следует поместить в шаблон (среди них - количества элементов в моделях). Данные представлены как пары ключ-значение, и могут быть получены в шаблоне по ключу.

Заметка:  В данном случае callback-функция, которую вызывает async.parallel() , несколько необычная - страница отображается всегда, независимо от того, была ошибка или нет (обычно используют отдельный путь выполнения для обработки выводимых ошибок).

Представление

Откройте файл  /views/index.pug и замените его содержимое текстом, приведенным ниже

extends layout

block content
  h1= title
  p Welcome to #[em LocalLibrary], a very basic Express website developed as a tutorial example on the Mozilla Developer Network.

  h1 Dynamic content

  if error
    p Error getting dynamic content.
  else
    p The library has the following record counts:

    ul
      li #[strong Books:] !{data.book_count}
      li #[strong Copies:] !{data.book_instance_count}
      li #[strong Copies available:] !{data.book_instance_available_count} 
      li #[strong Authors:] !{data.author_count}
      li #[strong Genres:] !{data.genre_count}

Представление несложное. Мы расширили базовый шаблон  layout.pug, переопределив блок (block) с именем 'content'. Первый заголовок h1 будет экранированным текстом - значением переменной title ,variable that  которая передается в функцию render() —заметьте, что применение 'h1='  говорит, что следующий текст рассматривается как выражение JavaScript. Затем расположен параграф, знакомящий с  LocalLibrary.

Под заголовком Dynamic content  мы проверяем, определена ли переданная из функции render() переменная error. Если да, отмечаем ошибку. Если нет, выводим ( как список) количества копий каждой модели, которые хранятся в переменной data.

Заметка:  Мы не экранируем количества элементов (т.е. используется синтаксис !{} ) потому что эти значения вычисляются. Если бы информация предоставлялась конечным пользователем, следовало бы экранировать переменную перед выводом.

Как это выглядит?

Сейчас у нас есть все для того, чтобы показать страницу index. Запустите приложение и откройте браузер с адресом http://localhost:3000/. Если все задано правильно, ваш сайт должен иметь примерно такой вид, как на приведенном снимке экрана.

Home page - Express Local Library site

Заметка:  Элементы бокового меню использовать еще нельзя, так как адреса, представления и шаблоны для этих страниц еще не определены. Если вы попытаетесь их использовать, будет выведено сообщение об ошибке, например,  вида "NOT IMPLEMENTED: Book list" (НЕ РЕАЛИЗОВАНО: список книг), в зависимости от выбранного элемента меню.  Эти строковые литералы (которые будут замещены действительными данными) были заданы в различных файлах контроллеров в каталоге "controllers".

Next steps

Метки документа и участники

Внесли вклад в эту страницу: mdnwebdocs-bot, alxatr
Обновлялась последний раз: mdnwebdocs-bot,