aboutsummaryrefslogtreecommitdiff
path: root/files/ru/learn/server-side/express_nodejs/routes
diff options
context:
space:
mode:
authorPeter Bengtsson <mail@peterbe.com>2020-12-08 14:42:52 -0500
committerPeter Bengtsson <mail@peterbe.com>2020-12-08 14:42:52 -0500
commit074785cea106179cb3305637055ab0a009ca74f2 (patch)
treee6ae371cccd642aa2b67f39752a2cdf1fd4eb040 /files/ru/learn/server-side/express_nodejs/routes
parentda78a9e329e272dedb2400b79a3bdeebff387d47 (diff)
downloadtranslated-content-074785cea106179cb3305637055ab0a009ca74f2.tar.gz
translated-content-074785cea106179cb3305637055ab0a009ca74f2.tar.bz2
translated-content-074785cea106179cb3305637055ab0a009ca74f2.zip
initial commit
Diffstat (limited to 'files/ru/learn/server-side/express_nodejs/routes')
-rw-r--r--files/ru/learn/server-side/express_nodejs/routes/index.html655
1 files changed, 655 insertions, 0 deletions
diff --git a/files/ru/learn/server-side/express_nodejs/routes/index.html b/files/ru/learn/server-side/express_nodejs/routes/index.html
new file mode 100644
index 0000000000..c8610eba1b
--- /dev/null
+++ b/files/ru/learn/server-side/express_nodejs/routes/index.html
@@ -0,0 +1,655 @@
+---
+title: 'Учебник Express часть 4: Маршруты и контроллеры'
+slug: Learn/Server-side/Express_Nodejs/routes
+translation_of: Learn/Server-side/Express_Nodejs/routes
+---
+<div>{{LearnSidebar}}</div>
+
+<div>{{PreviousMenuNext("Learn/Server-side/Express_Nodejs/mongoose", "Learn/Server-side/Express_Nodejs/Displaying_data", "Learn/Server-side/Express_Nodejs")}}</div>
+
+<p class="summary">В этом уроке мы настроим маршруты (код обработки URL) с "фиктивными" функциями-обработчиками для всех конечных точек ресурса, которые нам понадобятся на веб-сайте <a href="/en-US/docs/Learn/Server-side/Express_Nodejs/Tutorial_local_library_website">LocalLibrary</a>. По завершении мы получим модульную структуру для нашего кода обработки маршрута, который будет расширен реальными функциями-обработчиками в следующих статьях. У нас также будет хорошее понимание того, как создавать модульные маршруты с помощью Express!</p>
+
+<table class="learn-box standard-table">
+ <tbody>
+ <tr>
+ <th scope="row">
+ <table>
+ <tbody>
+ <tr>
+ <th scope="row">Предварительные знания:</th>
+ </tr>
+ </tbody>
+ </table>
+ </th>
+ <td>Прочесть  <a href="/en-US/docs/Learn/Server-side/Express_Nodejs/Introduction">введение в Express/Node </a>. Завершить предыдущие уроки (включая <a href="/en-US/docs/Learn/Server-side/Express_Nodejs/mongoose">Express Tutorial Part 3: Using a Database (with Mongoose)</a>).</td>
+ </tr>
+ <tr>
+ <th scope="row">Цель:</th>
+ <td>Понять, как создать простые маршруты. Настроить конечные точки URL.</td>
+ </tr>
+ </tbody>
+</table>
+
+<h2 id="Обзор">Обзор</h2>
+
+<p>В <a href="/en-US/docs/Learn/Server-side/Express_Nodejs/mongoose">последней статье </a>мы определили модели <em>Mongoose</em>  для взаимодействия с базой данных, и использовали (автономный) скрипт, который создал некоторые исходные записи библиотеки. Теперь можно написать код, чтобы представить эту информацию пользователям. Первое, что нужно сделать, это решить, какие возможности для отображения информации мы хотим иметь на наших страницах, а затем определить соответствующие URL-адреса для получения этих ресурсов. Затем нужно будет создать маршруты (обработчики URL-адресов) и представления (шаблоны) для отображения этих страниц.</p>
+
+<p>Приведенная ниже диаграмма напоминает об основном потоке данных и об элементах, которые необходимо реализовать при обработке HTTP-запроса/ответа. Кроме представлений и маршрутов на диаграмме показаны "контроллеры" - функции, которые отделяют код для маршрутизации запросов от кода, который фактически обрабатывает запросы.</p>
+
+<p>Поскольку модели уже созданы, основные элементы, которые следует создать, таковы:</p>
+
+<ul>
+ <li>"Маршруты" для перенаправления поддерживаемых запросов (и любой закодированной информации в URL-запросах) соответствующим функциям контроллера.</li>
+ <li>Контроллеры -функции для получения запрашиваемых данных из моделей, создание HTML страницы, отображающей данные, и возращение их пользователю для просмотра в браузере.</li>
+ <li>Представления (шаблоны), используемые контроллерами для отрисовки данных.</li>
+</ul>
+
+<p><img alt="" src="https://mdn.mozillademos.org/files/14456/MVC%20Express.png" style="height: 460px; width: 800px;"></p>
+
+<p>В итоге, у нас должны быть страницы для вывода списков  и  детальной информации по книгам, жанрам, авторам и экземплярам книг, а также страницы для создания, обновления и удаления записей. Это много для одной статьи. Поэтому большая часть этой статьи будет сосредоточена на настройке наших маршрутов и контроллеров для возврата "фиктивного" контента. Мы расширим методы контроллеров для работы с данными модели в следующих статьях .</p>
+
+<p>В первом разделе ниже приведен краткие основы того, как использовать промежуточное средство (middleware)  Express <a href="http://expressjs.com/en/4x/api.html#router">Router</a>. Эти знания будут использованы в следующих разделах при настройке  маршрутов для LocalLibrary.</p>
+
+<h2 id="Маршруты_-_основы">Маршруты - основы</h2>
+
+<p>Маршруты - это часть кода Express, связывающая HTTP действия (<code>GET</code>, <code>POST</code>, <code>PUT</code>, <code>DELETE</code>, etc.), URL пути (шаблона), и функцию, которая обрабатывает этот шаблон.</p>
+
+<p>Есть несколько способов создания маршрутов. В этом уроке мы используем промежуточные запросы <code><a href="http://expressjs.com/en/guide/routing.html#express-router">express.Router</a>,</code>  так как они позволяют группировать обработчики маршрутов для определенной части сайта и получать к ним доступ через общий префикс маршрута.  Все маршруты, связанные с библиотекой, будут сохранены в модуле "catalog", и если мы добавим маршруты для обработки учетных записей пользователей или других функций, мы сможем сгруппировать их отдельно.</p>
+
+<div class="note">
+<p><strong>Заметка:</strong> Маршруты приложения Express уже кратко рассматривались в <a href="https://developer.mozilla.org/en-US/docs/Learn/Server-side/Express_Nodejs/Introduction#Creating_route_handlers">Express Introduction &gt; Creating route handlers</a> (Введение -&gt; Создание обработчиков маршрутов).  Применение <em>Router </em>обеспечивает лучшую поддержку модульности (как обсуждается в первой подсекции ниже), а в остальном очень похоже на определение маршрутов непосредственно в объекте приложения <em>Express</em>.</p>
+</div>
+
+<p>В оставшейся части этого раздела представлен обзор того, как Router может быть использован  для определения маршрутов.</p>
+
+<h3 id="Определение_и_использование_отдельных_модулей_маршрутов">Определение и использование отдельных модулей маршрутов</h3>
+
+<p>Код ниже является реальным примером того, как можно создать модуль маршрута, а затем использовать его в приложении <em>Express</em>.</p>
+
+<p>Первым делом в модуле <strong>wiki.js </strong>создадим маршруты для wiki .  Код сначала импортирует объект приложения Express, использует его для получения объекта <code>Router</code> и затем, применяя метод <code>get(),</code> добавляет к объекту пару маршрутов. В завершение модуль экспортирует объект <code>Router</code> .</p>
+
+<pre class="brush: js"><code>// wiki.js - Wiki route module.
+
+var express = require('express');
+var router = express.Router();
+
+// Home page route.
+router.get('/', function (req, res) {
+ res.send('Wiki home page');
+})
+
+// About page route.
+router.get('/about', function (req, res) {
+ res.send('About this wiki');
+})
+
+module.exports = router;</code>
+
+</pre>
+
+<div class="note">
+<p><strong>Заметка:</strong> В примере callback-функции обработчиков маршрутов определены непосредственно в функциях роутеров. А в LocalLibrary мы определим эти callback-функции в отдельном модуле контроллера.</p>
+</div>
+
+<p>Чтобы использовать модуль роутера в главном приложении, прежде всего следует выполнить <code>require()</code> модуля маршрута (<strong>wiki.js</strong>). Потом вызовем <code>use()</code> для  приложения Express с аргументом, в котором указан URL-путь 'wiki', что добавит  Router к пути обработки промежуточного слоя.</p>
+
+<pre class="brush: js"><code>var wiki = require('./wiki.js');
+// ...
+app.use('/wiki', wiki);</code></pre>
+
+<p>После этого два маршрута, определенные в нашем модуле маршрутов wiki, станут доступны из <code>/wiki/</code> и <code>/wiki/about/</code>.</p>
+
+<h3 id="Функции_Route">Функции Route</h3>
+
+<p>В модуле выше определена пара типовых функций маршрута. Маршрут "about" (еще раз показан ниже) определен при помощи метода <code>Router.get()</code>, который отвечает только на  HTTP GET-запросы. Первый аргумент метода - URL-путь, а второй -  callback-функция, которая будет вызвана, если получен HTTP GET-запрос с указанным путем.</p>
+
+<pre class="brush: js"><code>router.get('/about', function (req, res) {
+ res.send('About this wiki');
+})</code>
+</pre>
+
+<p>Эта callback-функция имеет три аргумента takes three arguments (обычно именуемых как указано: <code>req</code>, <code>res</code>, <code>next</code>), которые соответствуют объекту HTTP запроса, ответу HTTP, и <em>следующей</em> <br>
+ функции в цепочке промежуточных элементов.</p>
+
+<div class="note">
+<p><strong>Заметка:</strong> Фукции в Router - это промежуточный слой (<a href="https://developer.mozilla.org/en-US/docs/Learn/Server-side/Express_Nodejs/Introduction#Using_middleware">middleware</a>) are <a href="https://developer.mozilla.org/en-US/docs/Learn/Server-side/Express_Nodejs/Introduction#Using_middleware">Express </a>, что означает, что они должны или завершить (ответить на) запрос reqили вызвать следующую (<code>next)</code> функцию в цепочке. В нашем случае запрос завершается вызовом <code>send()</code>, поэтому аргумент <code>next</code> не нужен (и поэтому не указан).</p>
+
+<p>Выше у функции роутера только один callback-аргумент, но можно указать столько таких аргументов, сколько хотите, или указать массив callback-функций. каждая из функций - это элемент в цепочке промежуточного слоя, и они будут вызываться в порядке их добавления в цепочку (если предыдущая функция не завершит запрос).</p>
+</div>
+
+<p>Здесь, когда приходит GET-запрос с путем ('<code>/about'</code>) callback-функция при ответе вызывает <code><a href="https://expressjs.com/en/4x/api.html#res.send">send()</a></code> , возвращая строку "About this wiki". Существует  <a href="https://expressjs.com/en/guide/routing.html#response-methods">ряд других методов ответа</a> , завершающих цикл запрос-ответ. Например, можно вызвать <code><a href="https://expressjs.com/en/4x/api.html#res.json">res.json()</a></code> , чтобы послать ответ JSON, или <code><a href="https://expressjs.com/en/4x/api.html#res.sendFile">res.sendFile()</a>,</code> чтобы послать файл. Метод ответа, который будет использован чаще всего при построении нашей библиотеки - это  <a href="https://expressjs.com/en/4x/api.html#res.render">render()</a>, создающий, на основе шаблонов и данных, и возвращающий  HTML-файлы —мы поговорим об этом подробнее в следующей статье!</p>
+
+<h3 id="HTTP_глаголы_(действия)">HTTP глаголы (действия)</h3>
+
+<p>Рассмотренный пример использует метод <code>Router.get()</code> для ответа на  HTTP GET- запросы с указанным путем.</p>
+
+<p>Кроме того, <code>Router</code> обеспечивает также методы маршрутизации для других HTTP глаголов, которые обычно используются точно таким же способом: <code>post()</code>, <code>put()</code>, <code>delete()</code>, <code>options()</code>, <code>trace()</code>, <code>copy()</code>, <code>lock()</code>, <code>mkcol()</code>, <code>move()</code>, <code>purge()</code>, <code>propfind()</code>, <code>proppatch()</code>, <code>unlock()</code>, <code>report()</code>, ​​​​​​ <code>mkactivity()</code>, <code>checkout()</code>, <code>merge()</code>, <code>m-</code><code>search()</code>, <code>notify()</code>, <code>subscribe()</code>, <code>unsubscribe()</code>, <code>patch()</code>, <code>search()</code>, и <code>connect()</code>.</p>
+
+<p>Например, код ниже делает то же, что и предыдущий, с путем <code>/about,</code> но отвечает на  HTTP POST-запросы.</p>
+
+<pre class="brush: js"><code>router.post('/about', function (req, res) {
+ res.send('About this wiki');
+})</code></pre>
+
+<h3 id="Маршруты_путей">Маршруты путей</h3>
+
+<p>Маршруты путей определяют конечные точки, в которых могут быть сделаны запросы.  В уже рассмотренных примерах это были просто строки, которые использовались точно так, как были записаны: '/', '/about', '/book', '/any-random.path'.</p>
+
+<p>Маршруты путей могут быть также образцами строк. Образцы строк используют подмножество синтаксиса регулярных выражений для определения <em>образцов</em> конечных точек, для которых должно проверяться соответствие. Подмножество приведено ниже (отметим, что перенос (<code>-</code>) и точка (<code>.</code>) в путях на основе строк понимаются буквально):</p>
+
+<ul>
+ <li>? : Конечная точка должна иметь 0 или 1 предыдущий символ. Так, путь маршрута <code>'/ab?cd'</code> соответствует конечным точкам <code>acd</code> или <code>abcd</code> (т.е. b может присутствовать или нет).</li>
+ <li>+ : Конечная точка должна иметь 1 или более предыдущих символов. Так, путь маршрута <code>'/ab+cd'</code> будет соответствовать конечным точкам <code>abcd</code>, <code>abbcd</code>, <code>abbbcd</code>, и так далее.</li>
+ <li>* : Конечная точка может содержать произвольную строку там, где находится символ '*'. Так, путь маршрута <code>'ab\*cd'</code> будет соответствовать конечным точкам <code>abcd</code>, <code>abXcd</code>, <code>abSOMErandomTEXTcd</code>, и так далее.</li>
+ <li>() : Группировка символов для выполнения другой операции. Так, <code>'/ab(cd)?e'</code> выполнит ?-проверку (0 или 1 появление) для группы (cd) — соответствия таковы: <code>abe</code> и <code>abcde</code>.</li>
+</ul>
+
+<p>Пути маршрутов могут быть также <a href="/en-US/docs/Web/JavaScript/Guide/Regular_Expressions">регулярными выражениями</a>  JavaScript. Например, путь маршрутов (ниже) будет соответствовать <code>catfish и</code> <code>dogfish</code>, но не <code>catflap</code>, <code>catfishhead</code>, и так далее. Отметим, регулярное выражение как путь использует синтаксис регулярных выражений (это не строка в кавычках, как в предыдущих случаях).</p>
+
+<pre class="brush: js"><code>app.get(/.*fish$/, function (req, res) {
+ ...
+})</code></pre>
+
+<div class="note">
+<p><strong>Заметка:</strong> Большинство наших маршрутов для библиотеки будут просто строками, а не образцами строк или регулярными выражениями. Кроме того, будут использоваться параметры маршрутов, что обсуждается в следующем разделе.</p>
+</div>
+
+<h3 id="Параметры_маршрутов">Параметры маршрутов</h3>
+
+<p>Параметры маршрутов - это <em>именованные сегменты URL</em> , которые используются для выбора значений из указанной позиции  URL. Именованные сегменты начинаются двоеточием, после которого следует имя (например, <code>/<strong>:</strong>your_parameter_name/</code>.  Выбранные значения сохраняются в объекте <code>req.params,</code> причем имя параметра  используется как ключ (т.е. <code>req.params.your_parameter_name</code>).</p>
+
+<p>Предположим, например, что URL содержит информацию о пользователях и книгах:  <code>http://localhost:3000/users/34/books/8989</code>. Можно извлечь эту информацию (см. ниже) в параметры <code>userId</code> и <code>bookId</code> пути:</p>
+
+<pre><code>app.get('/users/:userId/books/:bookId', function (req, res) {
+ // доступ к userId через: req.params.userId
+ // доступ к bookId через: req.params.bookId
+ res.send(req.params);
+})
+</code></pre>
+
+<p>Имена параметров пути должны состоять из “символов слова” (A-Z, a-z, 0-9, и _).</p>
+
+<div class="note">
+<p><strong>Заметка:</strong> URL <em>/book/create</em> будет соответствовать маршрутам вида <code>/book/:bookId</code> (и '<code>create</code>' станет значением "bookId"). Будет использован первый маршрут, соответствующий введенному  URL, поэтому, если необходимо обрабатывать URL вида <code>/book/create</code> отдельно, обработчик этого маршрута должен быть расположен до маршрута <code>/book/:bookId</code> .</p>
+</div>
+
+<p>Для начала этих сведений достаточно - если потребуется, можно найти дополнительную информацию в документации  Express: <a href="http://expressjs.com/en/starter/basic-routing.html">Basic routing</a> (основы маршрутизации) и <a href="http://expressjs.com/en/guide/routing.html">Routing guide</a> (руководство по маршрутизации).  В следующем разделе показано, как задать маршруты и контроллеры для нашей библиотеки LocalLibrary.</p>
+
+<h2 id="Маршруты_необходимые_для_библиотеки_LocalLibrary">Маршруты, необходимые для библиотеки LocalLibrary</h2>
+
+<p>Те URL, котрые в итоге будут нужны для наших страниц, показаны ниже.  Слово <em>object</em> должно быть заменено на имя каждой из наших моделей (book, bookinstance, genre, author),  слово <em>objects</em> - множественное число для <em>object, </em>а <em>id</em> - уникальное значение для поля(<code>_id</code>), которое Mongoose создает по умолчанию для каждого экземпляра модели.</p>
+
+<ul>
+ <li><code>catalog/</code> — Домашняя страница home/index.</li>
+ <li><code>catalog/&lt;objects&gt;/</code> — Список всех книг, экземпляров книг, жанров и авторов (т.е. /<code>catalog/books/</code>, /<code>catalog/genres/</code>, и т.д.)</li>
+ <li><code>catalog/&lt;object&gt;/<em>&lt;id&gt;</em></code> — Страница с подробностями для отдельной книги, экземпляра книги, жанра или автора с заданным полем идентификатора <code><em>_id</em></code>  (т.е. <code>/catalog/book/584493c1f4887f06c0e67d37)</code>.</li>
+ <li><code>catalog/&lt;object&gt;/create</code> — Форма для создания новой книги, экземпляра книги, жанра или автора (т.е. <code>/catalog/book/create)</code>.</li>
+ <li><code>catalog/&lt;object&gt;/<em>&lt;id&gt;</em>/update</code> —  Форма для обновления отдельной книги, экземпляра книги, жанра или автора с заданным идентификатором <code><em>_id</em></code>  (т.е. <code>/catalog/book/584493c1f4887f06c0e67d37/update)</code>.</li>
+ <li><code>catalog/&lt;object&gt;/<em>&lt;id&gt;</em>/delete</code> — Форма для удаления отдельной книги, экземпляра книги, жанра или автора по заданному идентификатору <code><em>_id</em></code> (т.е. <code>/catalog/book/584493c1f4887f06c0e67d37/delete)</code>.</li>
+</ul>
+
+<p>Первая домашняя страница и страницы со списками не кодируют никакой дополнительной информации. Хотя результаты, возвращаемые запросами, будут зависеть от типа модели и от содержимого БД, запросы для получения этой информации всегда будут одинаковы (подобно тому, как код для создания объектов всегда будет одним и тем же). </p>
+
+<p>В противоположность этому, другие URL используются для работы с  определенными экземплярами документов и моделей— индивидуальность элементов кодируется в  URL (как <code><em>&lt;id&gt;</em></code> выше). Параметры путей используются для извлечения информации и передачи ее в обработчик пути (и в следующей статье мы применим этот прием для того, чтобы динамически определять, какую информацию следует получить из БД). By encoding the information in our URL we only need one route for every resource of a particular type (e.g. one route to handle the display of every single book item).</p>
+
+<div class="note">
+<p><strong>Заметка</strong>: Express позволяет строить URL любым способом, который вам нравится — можно кодировать информацию в теле  URL как показано выше или использовать URL <code>GET</code> -запрос с параметрами (например, <code>/book/?id=6</code>). Какой бы подход вы не применяли, URL должны быть ясными, логичными и читаемыми (ознакомьтесь с советами<a href="https://www.w3.org/Provider/Style/URI"> W3C</a>).</p>
+</div>
+
+<p>Далее мы создадим callback-функции обработчиков маршрутов и код маршрутов для всех указанных выше URL.</p>
+
+<h2 id="Создаем_callback-функции_обработчиков_маршрутов">Создаем callback-функции обработчиков маршрутов</h2>
+
+<p>Перед определением маршрутов сначала создадим фиктивные (каркасные) callback-функции, которые они будут вызывать. Эти функции будут храниться в отдельных модулях -"контроллерах" для моделей Book, BookInstance, Genre, и Author (можно использовать любую структуру моделей и файлов, но кажется, что выбранная обеспечивает приемлемую модульность нашего проекта).</p>
+
+<p>Начнем с создания каталога для контроллеров в корне проекта (<strong>/controllers</strong>), а затем создадим отдельные файлы (модули) контроллеров для работы с моделями:</p>
+
+<pre>/express-locallibrary-tutorial //корень проекта
+ <strong>/controllers</strong>
+ <strong>authorController.js</strong>
+ <strong>bookController.js</strong>
+ <strong>bookinstanceController.js</strong>
+ <strong>genreController.js</strong></pre>
+
+<h3 id="Контроллер_автора">Контроллер автора</h3>
+
+<p>Скопируем следующий код в файл <strong>/controllers/authorController.js</strong>:</p>
+
+<pre class="brush: js">var Author = require('../models/author');
+
+// Показать список всех авторов.
+exports.author_list = function(req, res) {
+ res.send('NOT IMPLEMENTED: Author list');
+};
+
+// Показать подробную страницу для данного автора.
+exports.author_detail = function(req, res) {
+ res.send('NOT IMPLEMENTED: Author detail: ' + req.params.id);
+};
+
+// Показать форму создания автора по запросу GET.
+exports.author_create_get = function(req, res) {
+ res.send('NOT IMPLEMENTED: Author create GET');
+};
+
+// Создать автора по запросу POST.
+exports.author_create_post = function(req, res) {
+ res.send('NOT IMPLEMENTED: Author create POST');
+};
+
+// Показать форму удаления автора по запросу GET.
+exports.author_delete_get = function(req, res) {
+ res.send('NOT IMPLEMENTED: Author delete GET');
+};
+
+// Удалить автора по запросу POST.
+exports.author_delete_post = function(req, res) {
+ res.send('NOT IMPLEMENTED: Author delete POST');
+};
+
+// Показать форму обновления автора по запросу GET.
+exports.author_update_get = function(req, res) {
+ res.send('NOT IMPLEMENTED: Author update GET');
+};
+
+// Обновить автора по запросу POST.
+exports.author_update_post = function(req, res) {
+ res.send('NOT IMPLEMENTED: Author update POST');
+};
+</pre>
+
+<p>В модуле сначала подключается (requires) модель, которая далее будет использована для получения данных и их обновления. Далее экспортируются функции для каждого URL, который мы хотим обрабатывать (операции create-создать, update-обновить и delete-удалить используют формы, следовательно, должны быть дополнительные методы для обработки post-запросов от форм - эти методы обсуждаются далее, в статье "forms article" ("формы")).</p>
+
+<p>Все функции имеют стандартную форму функций среднего слоя <em>Express </em>, с арнументами для запроса, ответа и следующей <code>(next)</code> функции, которая должна быть вызвана, если метод не завершил цикл запроса (во всех приведенных в коде случаях - завершает!). Методы просто возвращают строку, информирующую о том, что соответствующая страница еще не создана. Если функция контроллера должна получить параметры маршрута, эти параметры будут выведены в строке сообщения (смотри выше <code>req.params.id</code> ).</p>
+
+<h4 id="BookInstance_controller">BookInstance controller</h4>
+
+<p>Скопируйте следующий код в файл <strong>/controllers/bookinstanceController.js</strong>  (он построен по образцу модуля контроллера для автора <code>Author</code> ):</p>
+
+<pre class="brush: js">var BookInstance = require('../models/bookinstance');
+
+// Display list of all BookInstances.
+exports.bookinstance_list = function(req, res) {
+ res.send('NOT IMPLEMENTED: BookInstance list');
+};
+
+// Display detail page for a specific BookInstance.
+exports.bookinstance_detail = function(req, res) {
+ res.send('NOT IMPLEMENTED: BookInstance detail: ' + req.params.id);
+};
+
+// Display BookInstance create form on GET.
+exports.bookinstance_create_get = function(req, res) {
+ res.send('NOT IMPLEMENTED: BookInstance create GET');
+};
+
+// Handle BookInstance create on POST.
+exports.bookinstance_create_post = function(req, res) {
+ res.send('NOT IMPLEMENTED: BookInstance create POST');
+};
+
+// Display BookInstance delete form on GET.
+exports.bookinstance_delete_get = function(req, res) {
+ res.send('NOT IMPLEMENTED: BookInstance delete GET');
+};
+
+// Handle BookInstance delete on POST.
+exports.bookinstance_delete_post = function(req, res) {
+ res.send('NOT IMPLEMENTED: BookInstance delete POST');
+};
+
+// Display BookInstance update form on GET.
+exports.bookinstance_update_get = function(req, res) {
+ res.send('NOT IMPLEMENTED: BookInstance update GET');
+};
+
+// Handle bookinstance update on POST.
+exports.bookinstance_update_post = function(req, res) {
+ res.send('NOT IMPLEMENTED: BookInstance update POST');
+};
+</pre>
+
+<h4 id="Контроллер_жанра">Контроллер жанра</h4>
+
+<p>Скопируйте следующий код в файл <strong>/controllers/genreController.js</strong> (он построен по образцу модулей контроллеров для автора <code>Author</code> и экземпляра книги <code>BookInstance</code>):</p>
+
+<pre class="brush: js">var Genre = require('../models/genre');
+
+// Display list of all Genre.
+exports.genre_list = function(req, res) {
+ res.send('NOT IMPLEMENTED: Genre list');
+};
+
+// Display detail page for a specific Genre.
+exports.genre_detail = function(req, res) {
+ res.send('NOT IMPLEMENTED: Genre detail: ' + req.params.id);
+};
+
+// Display Genre create form on GET.
+exports.genre_create_get = function(req, res) {
+ res.send('NOT IMPLEMENTED: Genre create GET');
+};
+
+// Handle Genre create on POST.
+exports.genre_create_post = function(req, res) {
+ res.send('NOT IMPLEMENTED: Genre create POST');
+};
+
+// Display Genre delete form on GET.
+exports.genre_delete_get = function(req, res) {
+ res.send('NOT IMPLEMENTED: Genre delete GET');
+};
+
+// Handle Genre delete on POST.
+exports.genre_delete_post = function(req, res) {
+ res.send('NOT IMPLEMENTED: Genre delete POST');
+};
+
+// Display Genre update form on GET.
+exports.genre_update_get = function(req, res) {
+ res.send('NOT IMPLEMENTED: Genre update GET');
+};
+
+// Handle Genre update on POST.
+exports.genre_update_post = function(req, res) {
+ res.send('NOT IMPLEMENTED: Genre update POST');
+};
+</pre>
+
+<h4 id="Контроллер_книги">Контроллер книги</h4>
+
+<p>Скопируйте следующий код в файл <strong>/controllers/bookController.js</strong>. Он построен по образцу других модулей контроллеров, но еще содержит функцию <code>index()</code> для вывода странички с приветствием:</p>
+
+<pre class="brush: js">var Book = require('../models/book');
+
+<strong>exports.index = function(req, res) {
+ res.send('NOT IMPLEMENTED: Site Home Page');
+};</strong>
+
+// Display list of all books.
+exports.book_list = function(req, res) {
+ res.send('NOT IMPLEMENTED: Book list');
+};
+
+// Display detail page for a specific book.
+exports.book_detail = function(req, res) {
+ res.send('NOT IMPLEMENTED: Book detail: ' + req.params.id);
+};
+
+// Display book create form on GET.
+exports.book_create_get = function(req, res) {
+ res.send('NOT IMPLEMENTED: Book create GET');
+};
+
+// Handle book create on POST.
+exports.book_create_post = function(req, res) {
+ res.send('NOT IMPLEMENTED: Book create POST');
+};
+
+// Display book delete form on GET.
+exports.book_delete_get = function(req, res) {
+ res.send('NOT IMPLEMENTED: Book delete GET');
+};
+
+// Handle book delete on POST.
+exports.book_delete_post = function(req, res) {
+ res.send('NOT IMPLEMENTED: Book delete POST');
+};
+
+// Display book update form on GET.
+exports.book_update_get = function(req, res) {
+ res.send('NOT IMPLEMENTED: Book update GET');
+};
+
+// Handle book update on POST.
+exports.book_update_post = function(req, res) {
+ res.send('NOT IMPLEMENTED: Book update POST');
+};
+</pre>
+
+<h2 id="Создание_модуля_для_маршрута_catalog">Создание модуля для маршрута catalog</h2>
+
+<p>Далее мы создадим маршруты для всех URL, необходимых веб-сайту<a href="#local_libary_routes"> LocalLibrary</a>, которые будут вызывать функции контроллеров, определенные в предыдущем разделе.</p>
+
+<p>Каркас приложения уже содержит каталог <strong>./routes</strong>, в котором есть маршруты для <em>index</em> и <em>users</em>. Внутри этого каталога создадим еще один файл маршрутов — <strong>catalog.js</strong> ( см. ниже).</p>
+
+<pre>/express-locallibrary-tutorial //the project root
+ /routes
+  index.js
+  users.js
+  <strong>catalog.js</strong></pre>
+
+<p>Скопируйте приведенный ниже код в файл <strong>/routes/</strong><strong>catalog.js</strong> :</p>
+
+<pre class="brush: js"><strong>var express = require('express');
+var router = express.Router();
+</strong>
+// Требующиеся модули контроллеров.
+var book_controller = require('../controllers/bookController');
+var author_controller = require('../controllers/authorController');
+var genre_controller = require('../controllers/genreController');
+var book_instance_controller = require('../controllers/bookinstanceController');
+
+/// BOOK ROUTES МАРШРУТЫ КНИГ///
+
+// GET catalog home page.
+router.get('/', book_controller.index);
+
+// GET request for creating a Book. NOTE This must come before routes that display Book (uses id).
+// GET запрос для создания книги. Должен появиться до маршрута, показывающего книгу(использует id)
+router.get('/book/create', book_controller.book_create_get);
+
+// POST request for creating Book.
+router.post('/book/create', book_controller.book_create_post);
+
+// GET request to delete Book.
+router.get('/book/:id/delete', book_controller.book_delete_get);
+
+// POST request to delete Book.
+router.post('/book/:id/delete', book_controller.book_delete_post);
+
+// GET request to update Book.
+router.get('/book/:id/update', book_controller.book_update_get);
+
+// POST request to update Book.
+router.post('/book/:id/update', book_controller.book_update_post);
+
+// GET request for one Book.
+router.get('/book/:id', book_controller.book_detail);
+
+// GET request for list of all Book items.
+router.get('/books', book_controller.book_list);
+
+/// AUTHOR ROUTES ///
+
+// GET request for creating Author. NOTE This must come before route for id (i.e. display author).
+// GET-запрос для создания автора. Должен появиться до маршрута для id (для вывода автора)
+router.get('/author/create', author_controller.author_create_get);
+
+// POST request for creating Author.
+router.post('/author/create', author_controller.author_create_post);
+
+// GET request to delete Author.
+router.get('/author/:id/delete', author_controller.author_delete_get);
+
+// POST request to delete Author.
+router.post('/author/:id/delete', author_controller.author_delete_post);
+
+// GET request to update Author.
+router.get('/author/:id/update', author_controller.author_update_get);
+
+// POST request to update Author.
+router.post('/author/:id/update', author_controller.author_update_post);
+
+// GET request for one Author.
+router.get('/author/:id', author_controller.author_detail);
+
+// GET request for list of all Authors.
+router.get('/authors', author_controller.author_list);
+
+/// GENRE ROUTES ///
+
+// GET request for creating a Genre. NOTE This must come before route that displays Genre (uses id).
+// GET-запрос для создания жанра. Должен появиться до маршрута, выводящего жанр (( с использованием id)
+router.get('/genre/create', genre_controller.genre_create_get);
+
+//POST request for creating Genre.
+router.post('/genre/create', genre_controller.genre_create_post);
+
+// GET request to delete Genre.
+router.get('/genre/:id/delete', genre_controller.genre_delete_get);
+
+// POST request to delete Genre.
+router.post('/genre/:id/delete', genre_controller.genre_delete_post);
+
+// GET request to update Genre.
+router.get('/genre/:id/update', genre_controller.genre_update_get);
+
+// POST request to update Genre.
+router.post('/genre/:id/update', genre_controller.genre_update_post);
+
+// GET request for one Genre.
+router.get('/genre/:id', genre_controller.genre_detail);
+
+// GET request for list of all Genre.
+router.get('/genres', genre_controller.genre_list);
+
+/// BOOKINSTANCE ROUTES ///
+
+// GET request for creating a BookInstance. NOTE This must come before route that displays BookInstance (uses id).
+// GET-запрос для создания экземпляра книги. Должен появиться до маршрута, выводящего BookInstance с использованием id
+router.get('/bookinstance/create', book_instance_controller.bookinstance_create_get);
+
+// POST request for creating BookInstance.
+router.post('/bookinstance/create', book_instance_controller.bookinstance_create_post);
+
+// GET request to delete BookInstance.
+router.get('/bookinstance/:id/delete', book_instance_controller.bookinstance_delete_get);
+
+// POST request to delete BookInstance.
+router.post('/bookinstance/:id/delete', book_instance_controller.bookinstance_delete_post);
+
+// GET request to update BookInstance.
+router.get('/bookinstance/:id/update', book_instance_controller.bookinstance_update_get);
+
+// POST request to update BookInstance.
+router.post('/bookinstance/:id/update', book_instance_controller.bookinstance_update_post);
+
+// GET request for one BookInstance.
+router.get('/bookinstance/:id', book_instance_controller.bookinstance_detail);
+
+// GET request for list of all BookInstance.
+router.get('/bookinstances', book_instance_controller.bookinstance_list);
+
+<strong>module.exports = router;</strong>
+</pre>
+
+<p>Модуль загружает Express и использует его для создания объекта <code>Router</code> . В маршутизаторе задаются маршруты и производится их экспорт.</p>
+
+<p>Маршруты определяют в объекте маршрутизатора  или <code>.get()</code> или <code>.post()</code> методы. Все пути заданы как строки (образцы строк и регулярные выражения не использовались). Маршруты, которые взаимодействуют с конкретным ресурсом (скажем, с книгой), для получения из URL идентификатора объекта используют параметры путей.</p>
+
+<p>Все функции-обработчики импортируются из созданных в предыдущем разделе модулей контроллеров.</p>
+
+<h3 id="Обновление_модуля_маршрута_index">Обновление модуля маршрута index</h3>
+
+<p>Все новые маршруты заданы, а маршрут на начальную страницу остался без изменения. Давайте перенаправим его на новую страницу "index", которая создана в каталоге  '/catalog'.</p>
+
+<p>Откройте <strong>/routes/index.js</strong> и замените существущий маршрут нприведенную ниже.</p>
+
+<pre class="brush: js">// GET home page.
+router.get('/', function(req, res) {
+ res.redirect('/catalog');
+});</pre>
+
+<div class="note">
+<p><strong>Заметка:</strong> Это первое использование метода ответа <a href="https://expressjs.com/en/4x/api.html#res.redirect">redirect()</a> . Он делает перенаправление на указанную страницу, и по умолчанию устанавливает код возврата HTTP в "302 Found" (найдено). Если требуется, можно изменить код возврата. Путь можно задавать как абсолютный или как относительный.</p>
+</div>
+
+<h3 id="Обновление_app.js">Обновление app.js</h3>
+
+<p>Завершающий шаг - добавление маршрутов в цепочку промежуточного слоя. Это будет сделано в <code>app.js</code>.</p>
+
+<p>Откройте файл <strong>app.js</strong> и поместите require для маршрута каталог  ниже других маршрутов (добавьте третью строку. показанную ниже, после имеющихся двух строк):</p>
+
+<pre class="brush: js">var indexRouter = require('./routes/index');
+var usersRouter = require('./routes/users');
+<strong>var catalogRouter = require('./routes/catalog'); //Import routes for "catalog" area of site</strong></pre>
+
+<p>Далее, добавьте маршрут каталога в стек промежуточного слоя после других маршрутов (добавтьте третью строку после имеющихся двух):</p>
+
+<pre class="brush: js">app.use('/', indexRouter);
+app.use('/users', usersRouter);
+<strong>app.use('/catalog', catalogRouter); // Add catalog routes to middleware chain.</strong></pre>
+
+<div class="note">
+<p><strong>Заметка:</strong> Мы добавили модуль каталога в путь<code>'/catalog'</code>.  Этот путь будет предшествовать всем путям, определенным в модуле каталога. Например, для доступа к списку книг URL будет таким: <code>/catalog/books/</code>.</p>
+</div>
+
+<p>Вот так. Теперь у нас есть пути и фиктивные функции, подготовленные для всех  URL, которые мы собираемся поддерживать на веб-сайте LocalLibrary.</p>
+
+<h3 id="Проверка_маршрутов">Проверка маршрутов</h3>
+
+<p>Чтобы проверить маршруты, сначала запустим веб-сайт обычным способом</p>
+
+<ul>
+ <li>Обычный способ
+ <pre class="brush: bash"><code>// Windows
+SET DEBUG=express-locallibrary-tutorial:* &amp; npm start
+
+// macOS or Linux
+DEBUG=express-locallibrary-tutorial:* npm start</code>
+</pre>
+ </li>
+ <li>Если предварительно установлен <a href="/en-US/docs/Learn/Server-side/Express_Nodejs/skeleton_website">nodemon</a>, для запуска можно использовать:
+ <pre><code>// Windows
+SET DEBUG=express-locallibrary-tutorial:* &amp; npm <strong>run devstart</strong>
+
+// macOS or Linux
+</code> DEBUG=express-locallibrary-tutorial:* npm <strong style="font-family: inherit; font-size: 1rem;">run devstart</strong>
+</pre>
+ </li>
+</ul>
+
+<p>После запуска перейдите к совокупности URL нашей LocalLibrary, и проверьте, что не появляется страница ошибки (HTTP 404). Небольшая часть наших URL для удобства приводится ниже:</p>
+
+<ul>
+ <li><a href="http://localhost:3000/">http://localhost:3000/</a></li>
+ <li><a href="http://localhost:3000/catalog">http://localhost:3000/catalog</a></li>
+ <li><a href="http://localhost:3000/catalog/books">http://localhost:3000/catalog/books</a></li>
+ <li><a href="http://localhost:3000/catalog/bookinstances/">http://localhost:3000/catalog/bookinstances/</a></li>
+ <li><a href="http://localhost:3000/catalog/authors/">http://localhost:3000/catalog/authors/</a></li>
+ <li><a href="http://localhost:3000/catalog/genres/">http://localhost:3000/catalog/genres/</a></li>
+ <li><a href="http://localhost:3000/catalog/book/5846437593935e2f8c2aa226/">http://localhost:3000/catalog/book/5846437593935e2f8c2aa226</a></li>
+ <li><a href="http://localhost:3000/catalog/book/create">http://localhost:3000/catalog/book/create</a></li>
+</ul>
+
+<h2 id="Итог">Итог</h2>
+
+<p>Созданы все маршруты для нашего сайта. Созданы также фиктивные функции контроллеров, которые мы полностью реализуем в последующих статьях. Попутно мы изучили массу базовых сведений о маршрутах Express, и ознакомились с  некоторыми подходами по структурированию маршрутов и контроллеров.</p>
+
+<p>В следующей статье мы создадим настоящую страничку приветствия нашего сайта, для чего используем представления (шаблоны) и данные, хранящиеся в наших моделях.</p>
+
+<h2 id="Смотрите_также">Смотрите также</h2>
+
+<ul>
+ <li><a href="http://expressjs.com/en/starter/basic-routing.html">Basic routing</a>  Основы маршрутизации (документация Express)</li>
+ <li><a href="http://expressjs.com/en/guide/routing.html">Routing guide</a>  Руководство по маршрутизации (документация Express)</li>
+</ul>
+
+<p>{{PreviousMenuNext("Learn/Server-side/Express_Nodejs/mongoose", "Learn/Server-side/Express_Nodejs/Displaying_data", "Learn/Server-side/Express_Nodejs")}}</p>
+
+
+
+<h2 id="In_this_module">In this module</h2>
+
+<ul>
+ <li><a href="/en-US/docs/Learn/Server-side/Express_Nodejs/Introduction">Express/Node introduction</a></li>
+ <li><a href="/en-US/docs/Learn/Server-side/Express_Nodejs/development_environment">Setting up a Node (Express) development environment</a></li>
+ <li><a href="/en-US/docs/Learn/Server-side/Express_Nodejs/Tutorial_local_library_website">Express Tutorial: The Local Library website</a></li>
+ <li><a href="/en-US/docs/Learn/Server-side/Express_Nodejs/skeleton_website">Express Tutorial Part 2: Creating a skeleton website</a></li>
+ <li><a href="/en-US/docs/Learn/Server-side/Express_Nodejs/mongoose">Express Tutorial Part 3: Using a Database (with Mongoose)</a></li>
+ <li><a href="/en-US/docs/Learn/Server-side/Express_Nodejs/routes">Express Tutorial Part 4: Routes and controllers</a></li>
+ <li><a href="/en-US/docs/Learn/Server-side/Express_Nodejs/Displaying_data">Express Tutorial Part 5: Displaying library data</a></li>
+ <li><a href="/en-US/docs/Learn/Server-side/Express_Nodejs/forms">Express Tutorial Part 6: Working with forms</a></li>
+ <li><a href="/en-US/docs/Learn/Server-side/Express_Nodejs/deployment">Express Tutorial Part 7: Deploying to production</a></li>
+</ul>