Отзывчивый дизайн - Изучение веб-разработки

Отзывчивый дизайн
=================

* Назад
* Обзор: CSS layout
* Далее  (en-US)

На заре веб-дизайна страницы создавались для экрана определённого размера. Если у пользователя был экран большего или меньшего размера чем ожидал дизайнер, то результат мог быть от нежелательных полос прокрутки, до слишком длинной строки и плохого использования пространства. Поскольку становились доступны много различных размеров экранов, появилась концепция *отзывчивого (адаптивного) веб-дизайна* *(responsive web design* (RWD)) — набор методов, которые позволяют веб-страницам менять свой макет и внешний вид в соответствии с разной шириной экрана, разрешением и т.д. Это та самая, идея которая изменила подход к дизайну веба для множества устройств, и в этой статье мы поможем вам понять основные методы, которые вам необходимо знать, чтобы освоить его.

| Необходимые знания: | Основы HTML (изучите Введение в HTML), идея о том как работает CSS (изучите Введение в CSS и Устройство CSS.) |
| --- | --- |
| Задача: | Понять базовые концепции и историю отзывчивого дизайна. |

Исторические макеты сайтов
--------------------------

В какой-то момент истории при разработке веб-сайта у вас было два варианта:

* Вы могли создать *жидкий* сайт, который будет растягиваться чтобы заполнить окно браузера
* или сайт с *фиксированной шириной*, который будет иметь фиксированный размер в пикселях.

Эти два подхода, как правило, приводили к тому, что веб-сайт лучше всего выглядел на экране человека, создавшего сайт! Жидкий сайт приводил к раздавленному дизайну на маленьких экранах (как видно ниже) и не читаемо длинным строкам на больших.

![A layout with two columns squashed into a mobile size viewport.](/ru/docs/Learn/CSS/CSS_layout/Responsive_Design/mdn-rwd-liquid.png)

**Примечание:** Посмотрите этот простой жидкий макет: пример, исходный код. При просмотре примера, растягивайте и сжимайте окно браузера чтобы увидеть, как это выглядит при разных размерах.

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

![A layout with a horizontal scrollbar in a mobile viewport.](/ru/docs/Learn/CSS/CSS_layout/Responsive_Design/mdn-rwd-fixed.png)

**Примечание:** Посмотрите этот простой макет с фиксированной шириной: пример, исходный код. Снова изучите результат по мере изменения размера окна браузера.

**Примечание:** Скриншоты выше сделаны используя Responsive Design Mode в Firefox DevTools.

Когда мобильный веб стал становиться реальностью с первыми функциональными телефонами, компании желающие охватить мобильники начали создавать в основном специальные мобильные версии своих сайтов, с различными URL (часто что-то наподобие *m.example.com* или *example.mobi*). Это означало, что необходимо было разрабатывать и поддерживать в актуальном состоянии две отдельные версии сайта.

Кроме того, эти мобильные сайты часто предлагали очень урезанный вариант. Поскольку мобильные гаджеты стали мощнее и способными отображать целые веб-сайты, пользователей мобильных устройств раздражало, что они обнаруживали себя запертыми в мобильной версии сайта, неспособные получить доступ к информации, которая, как они знали, есть в полнофункциональной версии сайта.

Гибкий макет до отзывчивого дизайна
-----------------------------------

Было разработано несколько подходов чтобы попытаться разрешить недостатки построения веб-сайтов жидким методом или методом с фиксированной шириной. В 2004 году Камерон Адамс написал пост Resolution dependent layout, описывающий метод создания дизайна который мог бы адаптироваться к разным разрешениям экрана. Этот подход требовал, чтобы JavaScript узнавал разрешение экрана и загружал корректный CSS.

Зои Миккели Гилленвотер сыграла важную роль в свой работе описав и формализовав различные способы посредствам которых могут быть созданы гибкие сайты, пытаясь найти золотую середину между заполнением экрана или полностью фиксированным размером.

Отзывчивый дизайн
-----------------

Термин адаптивный дизайн был Придуман Итаном Маркоттом в 2010 году и описывал использование трёх методов в сочетании.

1. Первой была идея жидких сеток, нечто что уже исследовала Гилленвотер, что можно прочитать в статье Маркотта - Fluid Grids (опубликовано в 2009 в A List Apart).
2. Вторым методом была идея жидких изображений. Используя очень простой метод настройки свойства `max-width` на `100%`, изображения будут становиться меньше если содержащий столбец становится уже чем изначальный размер изображения, но никогда не становится больше. Это позволяет изображению уменьшаться чтобы соответствовать столбцу гибких размеров, а не перекрываться с ним, но не расти и становиться пиксельным если столбец становится шире изображения.
3. Третьим ключевым компонентом были медиавыражения. Медиавыражения позволяют переключать тип макета применяя только CSS то, что Камерон Адамс исследовал, используя JavaScript. Вместо того чтобы иметь один макет для всех размеров экранов, макет мог изменяться. Боковые панели можно перемещать для маленьких экранов, либо отображать альтернативную навигацию.

Очень важно понять, что **адаптивный веб-дизайн** — **это не отдельная технология**, это термин используемый, чтобы описать подход к веб-дизайну или набор лучших практик, используемых для создания макета, который может реагировать на используемое устройство для просмотра контента. В первоначальном исследовании Маркотта это означало гибкие сетки (с использованием floats) и медиавыражения, однако почти за 10 лет, прошедших с момента написания этой статьи, адаптивная работа стала стандартом по умолчанию. Современные методы макета CSS отзывчивы по своей сути, и у нас есть новые штучки, встроенные в веб-платформу для того, чтобы делать дизайн отзывчивых сайтов проще.

Остальная часть этой статьи укажет вам на различные функции веб-платформы, которые вы, возможно, захотите использовать при создании адаптивного сайта.

Медиавыражения
--------------

Отзывчивый дизайн появился благодаря медиавыражениям (media queries). Спецификация Media Queries Level 3 стала Рекомендованным Кандидатом в 2009 году, что означает, что она была признана готовой к реализации в браузерах. Медиавыражения позволяют нам проводить серию тестов (например, является ли экран пользователя больше, чем определённая ширина или разрешение) и выборочно применять CSS к стилю страницы соответственно с нуждами пользователя.

Например, следующее медиавыражение проверяет отображается ли текущая страница как экранная медиа (а не как печатный документ) и имеет ли область просмотра ширину как минимум 800 px. CSS будет применяться к селектору `.container` только если эти две вещи истины.

```css
@media screen and (min-width: 800px) {
  .container {
    margin: 1em 2em;
  }
}
```

Вы можете добавлять несколько медиавыражений в пределах одной таблицы стилей, подстраивая весь ваш макет или его части так, чтобы наилучшим образом соответствовать разным размерам экрана. Точки, в которых применяются медиавыражения и меняется макет, известны как *контрольные точки.*

Общим подходом при использовании медиавыражений является создание простого одноколоночного макета для устройств с узкими экранами (например, мобильные телефоны), затем проверка для больших экранов и применение макета с несколькими столбцам, когда вы знаете, что у вас достаточно ширины экрана, чтобы уместить все. Такой подход часто называют **mobile first** дизайном.

Узнать больше о медиавыражениях можно в документации MDN.

Гибкие сетки
------------

Отзывчивые сайты не просто меняют свой макет между контрольными точками, они построены на гибких сетках. Гибкая сетка подразумевает что вам не надо заботиться о каждом возможном существующем размере устройства и строить для них идеальный макет в пикселях. Такой подход был бы невозможен имея широкое множество существующих устройств разных размеров, как и факт того, что даже на ПК люди не всегда используют браузер с развёрнутым до максимума окном.

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

В первые дни отзывчивого дизайна, нашим единственным вариантом выполнения было использование floats. Гибкий обтекаемый макет достигался путём присвоения каждому элементу процентной ширины удостоверившись, что итоговые значения в макете не превышают 100%. В своей оригинальной статье о плавучих сетках Маркотт подробно описал формулу для преобразования макета, созданного с использованием пикселей, в проценты.
```

target / context = result
```

Например, если размер нашего целевого столбца — 60 пикселей, а контекст (или контейнер) в котором он находится — 960 пикселей, то мы делим 60 на 960 чтобы получить значение которое мы можем использовать в нашем CSS, после переноса десятичной точки вправо на 2 цифры.

```css
.col {
  width: 6.25%; /\* 60 / 960 = 0.0625 \*/
}
```

Этот подход сегодня можно найти во многих местах в Интернете и он задокументирован здесь в разделе макетов в нашей статье Устаревших методов макетов (en-US). В вашей работе вероятно, что вы столкнётесь с веб-сайтами, использующими этот подход, поэтому стоит понимать его, даже если вы не будете строить современные сайты используя гибкие сетки основанные на float.

Следующий пример демонстрирует простой отзывчивый дизайн, с использованием медиавыражений и гибких сеток. На узких экранах макет отображает блоки, расположенные друг над другом:

![A mobile view of the layout with boxes stacked on top of each other vertically.](/ru/docs/Learn/CSS/CSS_layout/Responsive_Design/mdn-rwd-mobile.png)

На более широких экранах они перемещаются в два столбца:

![A desktop view of a layout with two columns.](/ru/docs/Learn/CSS/CSS_layout/Responsive_Design/mdn-rwd-desktop.png)

**Примечание:** вы можете найти живой пример и исходный код этого примера на GitHub.

Современные технологии макетов
------------------------------

Современные методы макетов такие как Макет с несколькими столбцами, Flexbox, и Grid являются отзывчивыми по умолчанию. Они все предполагают, что вы пытаетесь создать гибкую сетку и дают вам более лёгкий способ сделать так.

### Multicol

Самый старый из этих методов — это multicol, когда вы задаёте `column-count`, это отражает то на сколько столбцов вы хотите разбить ваш контент. Далее браузер рассчитывает их размер, размер, который изменится согласно размеру экрана.

```css
.container {
  column-count: 3;
}
```

Если вместо этого вы зададите `column-width`, то вы определите *минимальную* ширину. Браузер создаст столько столбцов той ширины, сколько будет комфортно умещаться в контейнер, а затем поделит оставшееся пространство между всеми столбцами. Поэтому число столбцов будет меняться согласно тому сколько имеется места.

```css
.container {
  column-width: 10em;
}
```

### Flexbox

В Flexbox, в качестве исходного поведения, flex элементы будут сжиматься и распределять пространство между элементами в соответствии с пространством в их контейнере. Изменяя значения `flex-grow` и `flex-shrink` вы можете указать, как вы хотите, чтобы предметы вели себя когда они сталкиваются с большим или меньшим пространством вокруг себя.

В примере ниже каждый flex элемент будет принимать равное количество пространства во flex контейнере используя запись `flex: 1` как описано в главе Flexbox: Гибкое изменение размеров flex элементов.

```css
.container {
  display: flex;
}

.item {
  flex: 1;
}
```

**Примечание:** В качестве примера мы перестроили простой отзывчивый макет выше, в этот раз используя flexbox. Вы видите что нас больше не надо использовать странные процентные значения для подсчёта размера столбцов: пример, исходный код.

### CSS grid

В макете CSS Grid единицы измерения `fr` позволяют распределять доступное пространство между дорожками сетки. Следующий пример создаёт grid контейнер с тремя дорожками размером `1fr`. Это создаст три вертикальные дорожки, каждая занимающая одну часть свободного пространства в контейнере. Вы можете узнать больше об этом подходе к созданию сетки в теме Изучение Макета Grid в разделе Гибкие grids с единицами fr.

```css
.container {
  display: grid;
  grid-template-columns: 1fr 1fr 1fr;
}
```

**Примечание:** версия grid макета ещё проще, поскольку мы можем определить столбцы в .wrapper: пример, исходный код.

Отзывчивые изображения
----------------------

Самый простой подход к отзывчивым изображениям был описан в ранних статьях Маркотта по отзывчивому дизайну. По сути, вы берёте изображение максимального размера, которое могло понадобиться, и уменьшаете его. Этот подход до сих пор используется и в большинстве таблиц стилей вы найдёте следующий CSS:

```css
img {
  max-width: 100%;
}
```

Существуют очевидные недостатки к этому подходу. Изображение может быть изображено намного меньше своего исходного размера, что является пустой тратой пропускной способности — пользователь мобильных может загружать изображение, в несколько раз превышающее размер того, что он фактически видит в окне браузера. Кроме того, вам может не понадобиться такое же соотношение сторон изображения на мобильном устройстве, как на компьютере. Либо, учитывая меньший размер изображения на мобильном телефоне, вы можете захотеть показать совсем другое изображение, которое легче понять на маленьком экране. Такие вещи можно достичь, просто уменьшая изображение.

Отзывчивые изображения, используя элемент `<picture>` и атрибуты `srcset` и `sizes` элемента `<img>` оба решают эти проблемы. Вы можете указать несколько размеров вместе с «подсказками» (метаданные, описывающие размер экрана и разрешение, для которых изображение лучше всего подходит), и браузер выберет наиболее подходящее изображение для каждого устройства, гарантируя, что пользователь загрузит изображение подходящего размера для устройства, которое они используют.

Вы также можете напрямую использовать изображения разных размеров, обеспечивая разное кадрирование или совершенно другое изображение для разных размеров экрана.

Вы можете найти подробное руководство по отзывчивым изображениям в разделе изучения HTML на MDN.

Отзывчивая типографика
----------------------

Элементом отзывчивого дизайна, не освещённого ранее в работе, была идея отзывчивой типографики. Главным образом, она описывает изменение размеров шрифта в зависимости от ширины экрана при помощи медиавыражений.

В этом примере, мы хотим задать нашему заголовку первого уровня `4rem`, что значит, что он будет в четыре раза больше нашего базового размера шрифта. Это очень большой заголовок! Мы хотим этот гигантский заголовок только на экранах больших размеров, поэтому мы сначала создаём меньший заголовок, а затем используем медиавыржаение, чтобы переписать его для больших экранов, если мы знаем, что у пользователя есть экран размером как минимум `1200px`.

```css
html {
  font-size: 1em;
}

h1 {
  font-size: 2rem;
}

@media (min-width: 1200px) {
  h1 {
    font-size: 4rem;
  }
}
```

Мы отредактировали наш приведённый выше пример отзывчивой сетки grid, чтобы он также включал в себя адаптивный тип, используя описанный метод. Вы можете видеть, как заголовок меняет размеры, когда макет переходит в версию с двумя столбцами.

В мобильных версиях заголовок меньше:

![A stacked layout with a small heading size.](/ru/docs/Learn/CSS/CSS_layout/Responsive_Design/mdn-rwd-font-mobile.png)

На компьютерах, однако, мы видим больший размер заголовка:

![A two column layout with a large heading.](/ru/docs/Learn/CSS/CSS_layout/Responsive_Design/mdn-rwd-font-desktop.png)

**Примечание:** смотрите этот пример в действии: пример, исходный код.

Такой подход к типографике показывает, что вам не нужно ограничиваться в использовании медиавыражений только изменением макета страницы. Они могут быть использоваться для настройки любого элемента, чтобы сделать его более удобным или привлекательным при других размерах экрана.

### Using viewport units for responsive typography

An interesting approach is to use the viewport unit `vw` to enable responsive typography. `1vw` is equal to one percent of the viewport width, meaning that if you set your font size using `vw`, it will always relate to the size of the viewport.

```css
h1 {
  font-size: 6vw;
}
```

The problem with doing the above is that the user loses the ability to zoom any text set using the `vw` unit, as that text is always related to the size of the viewport. **Therefore you should never set text using viewport units alone**.

There is a solution, and it involves using `calc()`. If you add the `vw` unit to a value set using a fixed size such as `em`s or `rem`s then the text will still be zoomable. Essentially, the `vw` unit adds on top of that zoomed value:

```css
h1 {
  font-size: calc(1.5rem + 3vw);
}
```

This means that we only need to specify the font size for the heading once, rather than set it up for mobile and redefine it in the media queries. The font then gradually increases as you increase the size of the viewport.

**Примечание:** See an example of this in action: example, source code.

The viewport meta tag
---------------------

If you look at the HTML source of a responsive page, you will usually see the following `<meta>` tag in the `<head>` of the document.

```html
<meta name="viewport" content="width=device-width,initial-scale=1" />
```

This meta tag tells mobile browsers that they should set the width of the viewport to the device width, and scale the document to 100% of its intended size, which shows the document at the mobile-optimized size that you intended.

Why is this needed? Because mobile browsers tend to lie about their viewport width.

This meta tag exists because when the original iPhone launched and people started to view websites on a small phone screen, most sites were not mobile optimized. The mobile browser would, therefore, set the viewport width to 960 pixels, render the page at that width, and show the result as a zoomed-out version of the desktop layout. Other mobile browsers (e.g. on Google Android) did the same thing. Users could zoom in and pan around the website to view the bits they were interested in, but it looked bad. You will still see this today if you have the misfortune to come across a site that does not have a responsive design.

The trouble is that your responsive design with breakpoints and media queries won't work as intended on mobile browsers. If you've got a narrow screen layout that kicks in at 480px viewport width or less, and the viewport is set at 960px, you'll never see your narrow screen layout on mobile. By setting `width=device-width` you are overriding Apple's default `width=960px` with the actual width of the device, so your media queries will work as intended.

**So you should *always* include the above line of HTML in the head of your documents.**

There are other settings you can use with the viewport meta tag, however in general the above line is what you will want to use.

* `initial-scale`: Sets the initial zoom of the page, which we set to 1.
* `height`: Sets a specific height for the viewport.
* `minimum-scale`: Sets the minimum zoom level.
* `maximum-scale`: Sets the maximum zoom level.
* `user-scalable`: Prevents zooming if set to `no`.

You should avoid using `minimum-scale`, `maximum-scale`, and in particular setting `user-scalable` to `no`. Users should be allowed to zoom as much or as little as they need to; preventing this causes accessibility problems.

Summary
-------

Responsive design refers to a site or application design that responds to the environment in which it is viewed. It encompasses a number of CSS and HTML features and techniques and is now essentially just how we build websites by default. Consider the sites that you visit on your phone — it is probably fairly unusual to come across a site that is the desktop version scaled down, or where you need to scroll sideways to find things. This is because the web has moved to this approach of designing responsively.

It has also become much easier to achieve responsive designs with the help of the layout methods you have learned in these lessons. If you are new to web development today you have many more tools at your disposal than in the early days of responsive design. It is therefore worth checking the age of any materials you are referencing. While the historical articles are still useful, modern use of CSS and HTML makes it far easier to create elegant and useful designs, no matter what device your visitor views the site with.

* Назад
* Обзор: CSS layout
* Далее  (en-US)
In this module
--------------

* Introduction to CSS layout
* Normal flow
* Flexbox
* Grid
* Floats
* Positioning
* Multiple-column layout
* Responsive design
* Beginner's guide to media queries (en-US)
* Legacy layout methods (en-US)
* Supporting older browsers (en-US)
* Fundamental layout comprehension assessment


Первые шаги в программировании веб-сайтов на стороне сервера - Изучение веб-разработки

Первые шаги в программировании веб-сайтов на стороне сервера
============================================================

В этом модуле, посвящённом программированию на стороне сервера, мы ответим на несколько фундаментальных вопросов о программировании серверной части: «что это такое?», «чем оно отличается от программирования клиентской части?» и «почему оно так полезно?». Затем последует обзор некоторых самых популярных веб-фреймворков для серверной части и руководство по выбору наиболее подходящего фреймворка для создания вашего первого сайта. Наконец, мы завершим этот модуль вводной статьёй о безопасности веб-сервера.

Прежде чем начать
-----------------

Для того, чтобы начать этот модуль, вам не нужно иметь никаких знаний о программировании серверной части или даже о любом виде программирования.

Вам нужно понимать "как работает веб". Мы рекомендуем вам сперва прочесть следующие темы:

* Что такое веб-сервер
* Какое программное обеспечение мне нужно для создания сайта?
* Как загружать файлы на веб-сервер?

С этими базовыми знаниями вы будете готовы работать с модулями этого раздела.

Руководства
-----------

Введение в серверную часть

Добро пожаловать на курс программирования серверной части MDN для начинающих! В этой первой статье мы посмотрим на программирование серверной части на высоком уровне, отвечая на вопросы такие как: "что это такое?", "чем оно отличается от программирования клиентской части?" и "почему это настолько востребовано?". После прочтения этой статьи вы будете понимать всю дополнительную мощь, доступную веб-сайтам посредством программирования на стороне сервера.

Обзор Клиент-Сервера

Теперь, когда вы познакомились с целью и потенциальными преимуществами программирования серверной части, мы собираемся узнать в подробностях, что случится, когда сервер получит "динамический запрос" от браузера. Так как большинство программ серверной части обрабатывает запросы и ответы практически одинаково, это поможет вам понять, что нужно делать при написании собственного кода.

Фреймворки серверной части

Последняя статья рассказывает о том, что нужно делать веб-приложению серверной стороны для ответа на запросы от веб-браузера. Мы покажем здесь, как веб-фреймворки могут упростить эти задачи и поможем вам подобрать подходящий фреймворк для вашего первого серверного веб-приложения.

Безопасность веб-сайта

Безопасность веб-сайта требует бдительности на всех этапах проектирования сайта и его использования. Эта вводная статья не сделает из вас гуру безопасности сайтов, но поможет узнать, какие первые важные шаги вы можете предпринять для повышения устойчивости вашего веб-приложения против наиболее распространённых угроз.

Аттестация
----------

Этот "обзорный" модуль не содержит никакой аттестации, поскольку мы даже не прилагаем здесь для вас никакого кода. Мы действительно надеемся, что на текущем этапе у вас сформировалось чёткое понимание того, какие виды функциональности вы можете предоставить, используя программирование на стороне сервера, и вы уже приняли решение по поводу фреймворка, который вы будете использовать для создания вашего первого сайта.


.htaccess ( hypertext access ) - Изучение веб-разработки

.htaccess ( hypertext access )
==============================

Название .htaccess происходит от "hypertext access". Это файл с расширением HTACCESS, который содержит различные настройки сервера apache. Он позволяет настраивать для текущей директории защиту паролем, редиректы и многое другое.

**Доступ к файлу**: файл htaccess может быть открыт для редактирования любым текстовым редактором, таким как стандартный блокнот Windows, Vim, Sublime Text или любым другим. Подсветка синтаксиса для файлов .htaccess встречается редко.

Применение
----------

**Перенаправления**: htaccess файлы часто используют для перенаправления трафика между веб-страницами, а также между разными доменами. Это простой и эффективный способ перенаправления трафика, так как перенаправление происходит до обработки запроса на стороне сервера. Перенаправление может быть временным и постоянным, с установкой соответствующего кода статуса.
```

Redirect 301 / http://example.com/       # Постоянное перенаправление на example.com
Redirect 302 / http://example.com/       # Временное перенаправление на example.com
```

**Блокирование**: htaccess также может блокировать доступ с определённого IP адреса или диапазона IP адресов. Блокирование часто используется, чтобы запретить доступ к директории для различных ботов и поисковых пауков.
```

deny from 146.0.74.205                   # Блокирует все запросы с адреса 146.0.74.205
```

**SSI или Server Side Include** : С помощью файла .htaccess можно настроить автоматическое подключение файлов в документ. При каждом запросе пользователя, указанные файлы автоматически будут подключены в начало или в конец документа. При этом в самом документе их подключать не нужно.
```

php_value auto_prepend_file "/real/path/to/file/functions.php" # Подключит файл function.php в начало документа
php_value auto_append_file "/real/path/to/file/footer.php" # Подключит файл footer.html в конец документа
```

**Настройка страниц с ошибками:** с помощью .htaccess можно перенаправлять пользователя на определённые страницы, при возникновении ошибок на сервере.
```

ErrorDocument 404 /notfound.html # Перенаправит пользователя на страницу notfound.html , при возникновении ошибки с кодом 404
ErrorDocument 500 /serverr.html  # Перенаправит пользователя на страницу serverr.html , при возникновении ошибки с кодом 500
```

Для дополнительной информации читайте статью Redirect your Traffic for Error Handling.

**Кеширование:** файл .htaccess может управлять кешированием данных веб-браузером пользователя. Это ускорит загрузку страниц и сократит количество передаваемой информации между сервером и клиентом.

**MIME типы**: смотрите статью correct MIME types (en-US) для большей информации.


Node.js server without a framework - Изучение веб-разработки

Node.js server without a framework
==================================

Здесь вы найдёте описание простого статического сервера, который построен сугубо на Node.js без использования какого-либо фреймворка .

Node.js может использовать множество фреймворков, которые могут помочь создать сервер

Наиболее популярные:

* Express: Один из наиболее популярных фреймворков.
* Hapi.js: Набирающий популярность фреймворк для построения приложений и сервисов
* Total: Этот фреймворк имеет богатую функциональность и не требует каких-либо дополнительных фреймворков или библиотек.

Конечно-же эти фреймворки могут и не подойти для каждого конкретного случая. Именно поэтому нужно знать как все работает изнутри, чтобы быть готовым сделать свой собственный сервер без каких-либо дополнительных зависимостей.

Пример
------

Вот так выглядит статический сервер на Node.js:

```js
var http = require("http");
var fs = require("fs");
var path = require("path");

http
  .createServer(function (request, response) {
    console.log("request ", request.url);

    var filePath = "." + request.url;
    if (filePath == "./") {
      filePath = "./index.html";
    }

    var extname = String(path.extname(filePath)).toLowerCase();
    var mimeTypes = {
      ".html": "text/html",
      ".js": "text/javascript",
      ".css": "text/css",
      ".json": "application/json",
      ".png": "image/png",
      ".jpg": "image/jpg",
      ".gif": "image/gif",
      ".svg": "image/svg+xml",
      ".wav": "audio/wav",
      ".mp4": "video/mp4",
      ".woff": "application/font-woff",
      ".ttf": "application/font-ttf",
      ".eot": "application/vnd.ms-fontobject",
      ".otf": "application/font-otf",
      ".wasm": "application/wasm",
    };

    var contentType = mimeTypes[extname] || "application/octet-stream";

    fs.readFile(filePath, function (error, content) {
      if (error) {
        if (error.code == "ENOENT") {
          fs.readFile("./404.html", function (error, content) {
            response.writeHead(404, { "Content-Type": "text/html" });
            response.end(content, "utf-8");
          });
        } else {
          response.writeHead(500);
          response.end(
            "Sorry, check with the site admin for error: " +
              error.code +
              " ..\n",
          );
        }
      } else {
        response.writeHead(200, { "Content-Type": contentType });
        response.end(content, "utf-8");
      }
    });
  })
  .listen(8125);
console.log("Server running at http://127.0.0.1:8125/");
```

Задание
-------

Попробуйте добавить в этот код описание как работает этот код. Как вариант ещё можно добавить функциональность динамических запросов.


Веб-фреймворк Django (Python) - Изучение веб-разработки

Веб-фреймворк Django (Python)
=============================

Django является чрезвычайно популярным и полнофункциональным серверным веб-фреймворком, написанным на Python. Данный модуль расскажет о том, почему Django один из самых популярных серверных веб-фреймворков, как установить среду разработки, и как начать использовать его для создания собственных веб-приложений.

Требования
----------

Перед началом работы с этим модулем вам не обязательно уже быть знакомым с Django. Вам бы пригодилось общее понимание того, что такое серверное веб-программирование и веб-фреймворки, почерпнутое, в идеале, из топиков другого нашего модуля Первые шаги серверного программирования веб-сайтов.

Рекомендуется базовое понимание концепций программирования и языка Python, но это не обязательно для освоения основных понятий.

**Примечание:** Python является одним из самых доступных в чтении и понимании для новичков языком программирования. Тем не менее, если вы захотите глубже понять этот модуль, в Интернете сейчас доступны многочисленные бесплатные книги и учебные пособия (новички в программирование возможно захотят посетить Python for Non Programmers на вики-страницах python.org).

Руководство
-----------

Введение в Django

В этой первой статье по Django мы ответим на вопрос "Что такое Django?" и сделаем обзор того, что делает этот веб-фреймворк особенным. Мы кратко рассмотрим основные особенности, включая некоторую продвинутую функциональность, на которой у нас не будет возможности подробно остановиться в этом модуле. Мы также покажем вам некоторые из основных строительных блоков приложения Django, чтобы дать вам представление о том, что он может сделать, прежде чем вы перейдёте к установке и начнёте экспериментировать.

Установка среды разработки Django

Теперь, когда вы знаете, что такое Django, мы покажем вам, как установить и протестировать среду разработки Django для Windows, Linux (Ubuntu) и Mac OS X — какую бы операционную систему вы не использовали, эта статья должна дать вам понимание того, что вам потребуется, чтобы начать разработку Django-приложений .

Учебник Django: Веб-сайт местной библиотеки

Первая статья в нашей серии практических уроков объясняет, что вы узнаете, и представит обзор веб-сайта «местной библиотеки», над которым мы будем работать и развиваться в последующих статьях.

Учебник Django часть 2: Создание скелета веб-сайта

В этой статье показано, как вы можете создать проект веб-сайта «каркас» в качестве основы, после чего вы сможете заполнить параметры сайта, urls, модели, представления и шаблоны.

Учебник Django часть 3: Использование моделей

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

Учебник Django часть 4: Django admin веб-сайта

Теперь, когда мы создали модели для сайта местной библиотеки, мы будем использовать Django Admin, чтобы добавить данные о книгах в библиотеке. Сначала мы покажем вам, как регистрировать и администрировать модели сайта а затем мы покажем вам, как входить в систему и создавать некоторые данные. В конце мы покажем некоторые способы дальнейшего улучшения представлений сайта.

Учебник Django часть 5: Создание главной страницы

Теперь мы готовы добавить код для отображения нашей первой полной страницы — главной страницы сайта местной библиотеки, которая показывает, сколько записей у нас есть для каждого типа модели, и предоставляет ссылки на боковых панелях на другие наши страницы. По пути мы получим практический опыт написания основных карт и представлений URL, получения записей из базы данных и использования шаблонов.

Учебник Django часть 6: Общий список и подробные представления

Это руководство расширяет наш сайт местной библиотеки, добавляя список и подробные страницы для книг и авторов. Здесь мы узнаем об общих представлениях на основе классов и покажем, как они могут уменьшить количество кода, который вы должны писать для случаев общего использования. Мы также перейдём к обработке URL-адресов более подробно, покажем, как выполнить базовое сопоставление шаблонов.

Учебник Django часть 7: Структура сессий

Это руководство расширяет наш сайт местной библиотеки, добавляя счётчик посещений домашней страницы. Это относительно простой пример, но он показывает, как вы можете использовать структуру сессии, чтобы обеспечить постоянное поведение анонимных пользователей на ваших собственных сайтах.

Учебник Django часть 8: Авторизация и права пользователей

В этом уроке мы покажем вам, как разрешить пользователям входить на ваш сайт со своими учётными записями и как управлять тем, что они могут делать и видеть на основе того, зарегистрированы ли они или нет, и их допусках. В рамках этой демонстрации мы расширим сайт местной библиотеки, добавив страницы входа и выхода, а также страницы пользователей и персональные страницы для просмотра книг, которые были взяты на руки.

Учебник Django часть 9: Работа с формами

В этом уроке мы покажем вам, как работать с HTML Forms в Django, и в частности, самый простой способ писать формы для создания, обновления и удаления экземпляров модели. В рамках этой демонстрации мы расширим сайт местной библиотеки, чтобы библиотекари могли вносить новые книги, создавать, обновлять и удалять авторов, используя наши собственные формы (а не использовать приложение администратора).

Учебник Django часть10: Тестирование веб-приложения Django

По мере роста веб-сайтов становится сложнее проверять вручную — требуется больше проверок, поскольку взаимодействие между компонентами усложняется, небольшое изменение в одной области может потребовать дополнительные тесты для проверки его влияния на другие области. Один из способов смягчить эти проблемы - написать автоматизированные тесты, которые можно легко и надёжно запускать каждый раз, когда вы вносите изменения. В этом руководстве показано, как автоматизировать модульное тестирование вашего сайта с помощью тестовой среды Django.

Учебник Django часть 11: Деплой Django на продакшн

Теперь вы создали (и протестировали) удивительный сайт местной библиотеки, вам захочется установить его на общедоступный веб-сервер, чтобы к нему мог получить доступ персонал библиотеки и пользователи Интернета. В этой статье представлен обзор того, как вы можете найти хост для развёртывания вашего веб-сайта и что вам нужно сделать, чтобы подготовить ваш сайт к выпуску.

Безопасность веб-приложений Django

Защита пользовательских данных является неотъемлемой частью любой разработки сайта. Ранее мы объяснили некоторые из наиболее распространённых угроз безопасности в статье Web security — Эта статья даёт практическую демонстрацию того, как встроенные средства защиты Django справляются с такими угрозами.

Задания
-------

Следующее задание проверит ваше понимание того, как создать сайт с помощью Django, как описано в руководствах, перечисленных выше.

DIY Django мини-блог

В этом задании вы будете использовать некоторые знания, которые вы узнали из этого модуля, чтобы создать свой собственный блог.


Веб-фреймворк Express (Node.js/JavaScript) - Изучение веб-разработки

Веб-фреймворк Express (Node.js/JavaScript)
==========================================

Express представляет собой популярный веб-фреймворк, написанный на JavaScript и работающий внутри среды исполнения node.js. Этот модуль освещает некоторые ключевые преимущества этого фреймворка, установку среды разработки и выполнение основных задач веб-разработки и развёртывания.

Предварительные требования
--------------------------

Перед началом этого модуля вам необходимо представлять, что из себя представляет серверное программирование и веб-фреймворки, желательно из прочтения статей другого модуля Server-side website programming first steps. Знакомство с основными концепциями программирования и языком программирования JavaScript будет очень полезным, но оно не является обязательным для понимания базовых понятий этого модуля.

**Примечание:** Этот веб-сайт содержит множество источников для изучения JavaScript *в контексте разработки на стороне клиента*: JavaScript, JavaScript Guide, JavaScript Basics, JavaScript (изучение). Ключевые особенности и концепции языка JavaScript остаются сходными и для серверной разработки на Node.js и используемый материал достаточно релевантен. Node.js предоставляет additional APIs для обеспечения функциональности, которая полезна для "безбраузерной" разработки, т.е. для создания HTTP-сервера и доступа к файловой системе, но не поддерживает JavaScript APIs для работы с браузером и DOM.

Это руководство обеспечит вас некоторой информацией о работе с Node.js и Express, но также существуют и другие многочисленные отличные ресурсы в Интернете и книгах — некоторые из них доступны из тем How do I get started with Node.js (StackOverflow) и What are the best resources for learning Node.js? (Quora).

Руководства
-----------

Введение в Express/Node

В первой статье об Express мы ответим на вопросы "Что такое Node?" и "Что такое Express?" и дадим вам представление о том, что делает веб-фреймворк Express особенным. Мы расскажем об основных функциях и покажем вам некоторые из основных строительных блоков приложений Express (хотя на данный момент у вас ещё нет среды разработки, в которой можно её протестировать).

Настройка среды разработки Node (Express)

Теперь, когда вы знаете, что такое Express, мы покажем вам, как настроить и протестировать среду разработки Node/Express в Windows, Linux (Ubuntu) и Mac OS X. Независимо от того, какую популярную операционную систему вы используете, эта статья даст вам то, что вам нужно, чтобы начать разработку приложений Express.

Учебник Express: сайт LocalLibrary

Первая статья в нашей серии практических уроков объясняет, что вы будете изучать, и предоставит обзор веб-сайта «локальной библиотеки», над которым мы будем работать и развивать в последующих статьях.

Учебник Express часть 2: Создание скелета веб-сайта

В этой статье показано, как вы можете создать «скелет» веб-сайта, который затем можно будет заполнить с помощью маршрутов сайта, шаблонов/представлений и баз данных.

Учебник Express часть 3: Использование базы данных (с помощью Mongoose)

В этой статье кратко представлены базы данных для Node/Express. Затем показывается, как мы можем использовать Mongoose для обеспечения доступа к баз данных для сайта *LocalLibrary*. В уроке объясняется, как объявляются объектная схема и модели, основные типы полей и базовая валидация. Также кратко показаны некоторые из основных способов доступа к данным модели.

Учебник Express часть 4: Маршруты и контроллеры

В этом уроке мы создадим маршруты (код обработки URL) с "фиктивным" обработчиком функций для всех конечных точек ресурсов, которые нам в конечном итоге понадобятся для сайта *LocalLibrary*. По завершении мы будем иметь модульную структуру нашего кода обработки маршрута, который мы можем расширить с помощью функций реального обработчика в следующих статьях. Мы также будем очень хорошо понимать, как создавать модульные маршруты, используя Express.

Учебник Express часть 5: Отображение данных библиотеки

Теперь мы готовы добавить страницы, на которых будут отображаться книги веб-сайта *LocalLibrary* и другие данные. Страницы будут включать главную страницу, которая показывает сколько записей определённого типа мы имеем и отдельную страницу для детального просмотра записи. По пути мы получим практический опыт в получении записей из баз данных и использовании шаблонов.

Учебник Express часть 6: Работы с формами

В этой части мы покажем вам, как работать с HTML формами в Express, используя Pug, и в частности, как создавать, обновлять и удалять документы из базы данных.

Учебник Express часть 7: Выкладка в production (en-US)

Теперь когда вы создали восхитительный сайт *LocalLibrary*, вы захотите установить его на общедоступном сервере, чтобы он мог дать доступ персоналу библиотеки и пользователям в Интернет. В этой статье представлен обзор того, как вы можете найти хост для развёртывания вашего сайта и что вам нужно сделать, чтобы подготовить ваш сайт к публикации.

Смотрите также
--------------

Установка LocalLibrary на PWS/Cloud Foundry

В этой статье представлена практическая демонстрация того, как установить *LocalLibrary* на облаке Pivotal Web Services PaaS — это полнофункциональная альтернатива с открытым исходным кодом для Heroku, облачного сервиса PaaS используемого в части 7 этого учебника, представленного выше. PWS/Cloud Foundry определённо стоит попробовать, если вы ищете альтернативу Heroku (или другому PaaS облачному сервису), или просто хотите попробовать что-то другое.

Изучите другие учебники
-----------------------

Это все статьи учебника (на данный момент). Если вы хотите продолжить обучение, есть другие интересные темы:

* Использование сессий
* Авторизация пользователей
* Авторизация пользователей и уровни доступа
* Тестирование веб приложений Express
* Веб безопасность для веб приложений Express.

И, конечно, было бы неплохо создать какой-либо проверочный тест знаний!


Учебник Express часть 3: Использование базы данных (с помощью Mongoose) - Изучение веб-разработки

Учебник Express часть 3: Использование базы данных (с помощью Mongoose)
=======================================================================

* Назад
* Обзор: Express Nodejs
* Далее

В этой статье даётся краткое введение в базы данных, и методика их использования в приложениях Node/Express. Затем мы покажем, как можно использовать Mongoose для доступа к базе данных веб-сайта LocalLibrary. Мы объясним, как объявляются схемы и модели объектов, укажем основные типы полей, и методику базовой валидации. В статье также кратко показаны основные методы доступа к данным модели.

| Предварительные сведения: | Express Tutorial Part 2: Creating a skeleton website |
| --- | --- |
| Цель: | Уметь спроектировать и создать свои модели, используя Mongoose. |

Обзор
-----

Сотрудники библиотеки будут использовать сайт Local Library для хранения информации о книгах и абонентах, а абоненты библиотеки будут использовать его для просмотра и поиска книг, для получения информации о доступных копиях, для резервирования или одалживания книг. Чтобы эффективно хранить и извлекать информацию, мы будем хранить её в базе данных.

Express-приложения могут использовать различные базы данных, и есть несколько подходов, которые можно использовать для выполнения операций **C**reate, **R**ead, **U**pdate and **D**elete (CRUD) (создать, прочесть, обновить, удалить). В руководстве дан краткий обзор некоторых доступных опций, и детально рассмотрены некоторые механизмы работы.

### Какие базы данных можно использовать?

\*Express-\*приложение может использовать любые базы данных, поддерживаемые *Node* (сам по себе Express не определяет каких-либо конкретных дополнительных свойств и требований для управления базами данных). Есть много популярных вариантов — PostgreSQL, MySQL, Redis, SQLite, и MongoDB.

При выборе базы данных следует учитывать такие факторы как время разработки, время обучения, простота репликации и копирования, расходы, поддержка сообщества и т. д. Хотя нет единственной "лучшей" базы данных, почти любое из популярных решений будет приемлемым для сайта малого и среднего размера, такого как наша Local Library.

Более подробно о вариантах смотрите в: Database integration (Express docs).

### Каков наилучший способ взаимодействия с базой данных?

Существует два подхода при работе с базой данных:

* Использование родного языка запросов баз данных (т.е. SQL)
* Использование объектной модели данных (ODM) или объектно-реляционной модели (ORM). ODM / ORM представляют данные веб-сайта как объекты JavaScript, которые затем отображаются на поддерживающую базу данных. Некоторые ORM привязаны к определённой базе данных, тогда как другие не зависят от конкретной базы данных.

Наилучшую производительность можно получить с помощью SQL или другого языка запросов, поддерживаемого базой данных. Объектные модели (ODM) часто медленнее, потому что требуют перевода объектов в формат базы данных, при этом не обязательно будут использованы наиболее эффективные запросы к базе данных (особенно, если ODM предназначена для различных баз данных и должна идти на большие компромиссы в смысле поддержки тех или иных функций базы данных).

Преимущество применения ORM состоит в том, что программисты могут сосредоточиться на объектах JavaScript, а не на семантике базы данных — особенно, если требуется работать с разными базами данных (на одном или разных веб-сайтах). Они также дают очевидное место для валидации и проверки данных.

**Примечание:** Совет: Применение ODM / ORMs часто приводит к снижению затрат на разработку и обслуживание! Если вы не очень хорошо знакомы с языком запросов базы данных или если производительность не имеет первостепенного значения, следует серьёзно рассмотреть возможность применения ODM.

### Какую модель ORM/ODM следует использовать?

Есть много ODM/ORM доступных решений на сайте менеджера пакетов NPM (проверьте теги по подгруппе odm и orm).

Популярные решения на момент написания статьи:

* Mongoose: — это средство моделирование объектов базы данных MongoDB, предназначенное для асинхронной работы.
* Waterline: ORM фреймворка Sails (основан на Express) . Она предоставляет единый API для доступа к множеству баз данных, в том числе Redis, mySQL, LDAP, MongoDB, и Postgres.
* Bookshelf: поддерживает как promise- так и традиционные callback- интерфейсы, поддержка транзакций, eager/nested-eager relation loading, полиморфные ассоциации, и поддержка, один к одному, один ко многим, и многие ко многим. Работает с PostgreSQL, MySQL, и SQLite3.
* Objection: Делает настолько лёгким, насколько возможно, использование всей мощи SQL и движка базы данных ( поддерживает SQLite3, Postgres, и MySQL).
* Sequelize: Основанная на промисах ORM для Node.js и io.js. Поддерживает диалекты PostgreSQL, MySQL, MariaDB, SQLite и MSSQL, обладает надёжной поддержкой транзакций, отношений, чтения копий и т.д.
* Node ORM2 — это OR менеджер для NodeJS. Поддерживает MySQL, SQLite и Progress, помогает работать с БД, используя объектный подход.
* JugglingDB — это кросс-ДБ ORM для NodeJS, обеспечивающая общий интерфейс для доступа к наиболее популярным форматам БД. Поддерживает MySQL, SQLite3, Postgres, MongoDB, Redis и хранение данных в памяти js (собственный движок, только для тестирования).

Как правило, при выборе решения следует учитывать как предоставляемые функции, так и "деятельность сообщества" ( загрузки, вклад, отчёты об ошибках, качество документации, и т.д. ) . На момент написания статьи Mongoose являлась очень популярной ORM, и разумно, если вы выбрали MongoDB.

### Применение Mongoose и MongoDb для LocalLibrary

В примере LocalLibrary (и до конца раздела) мы будем использовать Mongoose ODM для доступа к данным нашей библиотеки. Mongoose является интерфейсом для MongoDB, NoSQL-базы данных с открытым исходным кодом, в которой использована документов-ориентированная модель данных. В MongoDB «коллекции» и «документы» — это аналоги «таблиц» и «строк» в реляционных БД.

Это сочетание ODM и БД весьма популярно в сообществе Node, частично потому, что система хранения документов и запросов очень похожа на JSON и поэтому знакома разработчикам JavaScript.

**Примечание:** Не обязательно знать MongoDB, чтобы использовать Mongoose, хотя документацию Mongoose легче использовать и понимать, если вы уже знакомы с MongoDB.

Далее показано, как определить и получить доступ к схеме и моделям Mongoose для примера веб-сайта LocalLibrary.

Проектирование моделей LocalLibrary
-----------------------------------

Прежде чем начинать писать код моделей, стоит обдумать, какие данные нам нужно хранить, и каковы отношения между разными объектами.

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

При проектировании моделей имеет смысл иметь отдельные модели для каждого «объекта» (группы связанных данных). В этом случае очевидными объектами являются книги, экземпляры книг и авторы.

Можно также использовать модели для представления параметров списка выбора (например, как выпадающий список вариантов), вместо жёсткого кодирования выбора на самом веб-сайте - рекомендуется, когда не все параметры известны или могут быть изменены. Явный кандидат для модели такого типа — это жанр книги (например, «Научная фантастика», «Французская поэзия» и т.д.),

Как только мы определились с моделями и полями, следует подумать об отношениях между ними.

С учётом сказанного, UML-диаграмма связей (см. ниже) показывает модели, которые представлены как прямоугольники. Мы решили, что создадим модели для книги (общие сведения о книге), для экземпляра книги (состояние отдельных физических копий книги, доступных в системе) и для автора. Кроме того, у нас будет модель для жанра, чтобы эти значения можно было создавать динамически. Решено не создавать модель для `BookInstance:status` — мы пропишем в коде необходимые значения, потому что не ожидаем их изменения. На элементах диаграммы показаны имя модели, имена и типы полей, имена методов и типы их результатов .

Также показаны отношения между моделями, включая множественные отношения. Числа на линиях связи показывают максимум и минимум моделей, участвующих отношении. Например, линия между `Book` и `Genre` показывает, что `Book` и `Genre` связаны. Числа на этой линии рядом с моделью `Book` показывают, что жанр может быть связан с любым количеством книг, а числа на другом конце линии рядом с `Genre` отмечают, что книга может быть связана с любым количеством жанров.

**Примечание:** Как показано в Учебнике по Mongoose ниже, часто лучше иметь поле, определяющее отношение между документами (моделями), только в одной модели (обратное отношение можно найти по присвоенному идентификатору `_id` в другой модели). Ниже мы предпочли задать отношения между Book/Genre и между Book/Author в схеме Book, а отношение между Book/BookInstance — в схеме BookInstance. Этот выбор в некотором смысле был произвольным — таким же хорошим мог бы быть выбор другого поля в другой схеме.

![Mongoose Library Model with correct cardinality](/ru/docs/Learn/Server-side/Express_Nodejs/mongoose/library_website_-_mongoose_express.png)

**Примечание:** В следующем разделе дан базовый учебник, в котором объясняется, как задавать и как использовать модели. При чтении обратите внимание, как будут создаваться модели, приведённые на диаграмме.

Учебник по Mongoose
-------------------

В этом разделе кратко описано как подключиться к базе MongoDB с помощью Mongoose, как определить схемы и модели, как сформировать основные запросы.

**Примечание:** На этот учебник значительно повлияло руководство Mongoose quick start на *npm* и официальная документация.

### Установка Mongoose и MongoDB

Mongoose устанавливается в ваш проект (**package.json**) как и другие зависимости - при помощи NPM. Команда установки (выполняется из каталога проекта):

```bash
npm install mongoose
```

Установка *Mongoose* добавит все зависимости, включая драйвер MongoDB, но не установит саму базу данных. При желании установить сервер MongoDB локально, можно скачать установочный файл здесь для своей операционной системы и установить его. Также можно использовать облако MongoDB.

**Примечание:** В примере для хранения базы данных мы используем облачный сервис sandbox tier ("песочницу"). Это удобно для разработки и имеет смысл для руководства, потому что такой подход делает "установку" базы данных независимой от операционной системы (база данных как веб-сервис — это также подход, который вы можете использовать для своей базы данных, находящейся в реальной эксплуатации).

### Подключение к MongoDB

*Mongoose* требует подключение к MongoDB. Вы можете использовать require() и подключится к локальной БД при помощи `mongoose.connect(),` как показано ниже.

```js
// Импортировать модуль mongoose
var mongoose = require("mongoose");

// Установим подключение по умолчанию
var mongoDB = "mongodb://127.0.0.1/my\_database";
mongoose.connect(mongoDB);
// Позволим Mongoose использовать глобальную библиотеку промисов
mongoose.Promise = global.Promise;
// Получение подключения по умолчанию
var db = mongoose.connection;

// Привязать подключение к событию ошибки (получать сообщения об ошибках подключения)
db.on("error", console.error.bind(console, "MongoDB connection error:"));
```

При помощи `mongoose.connection` можно получить стандартный объект `Connection`. После подключения в экземпляре `Connection` возникает событие open (открыт).

**Примечание:** Если необходимо создать дополнительные подключения, можно использовать `mongoose.createConnection()`. При этом будут применены те же БД URI (хост, БД, порт, опции и т.д.), что и в `connect()` и будет возвращён объект `Connection`.

### Определение и создание моделей

Модели можно создать при помощи интерфейса `Schema` . Schema позволяет указать поля, которые будут в каждом документе, значения полей по умолчанию и требования по валидации. Кроме того, можно задать статические методы и методы-хелперы (от help), облегчающие работу с вашими типами данных, а также задать виртуальные свойства, которые можно использовать как и обычные поля, но без влияния на данные в самой базе данных.

Схемы "компилируются " в окончательную модель методом `mongoose.model()`. После создания модели её можно использовать для поиска, создания, обновления и удаления объектов данного типа.

**Примечание:** Каждой модели соответствует *коллекция* *документов* в ДБ MongoDB. Документы будут содержать поля тех типов, которые заданы в модели `Schema`.

#### Определение схем данных

Код ниже показывает, как можно задать простую схему. Сначала при помощи `require()` создаётся объект mongoose, затем конструктор Schema создаёт новый экземпляр схемы, при этом различные поля задаются как параметры конструктора.

```js
//Требуется Mongoose
var mongoose = require("mongoose");

//Определяем схему
var Schema = mongoose.Schema;

var SomeModelSchema = new Schema({
  a\_string: String,
  a\_date: Date,
});
```

В примере созданы два поля, типа String и типа Date. В следующем разделе будут примеры полей других типов, их валидации и примеры других методов.

#### Создание модели

Модели создаются из схем методом `mongoose.model()`:

```js
// Определяем схему
var Schema = mongoose.Schema;

var SomeModelSchema = new Schema({
  a\_string: String,
  a\_date: Date,
});

// Компилируем модель из схемы
var SomeModel = mongoose.model("SomeModel", SomeModelSchema);
```

Первый аргумент - уникальное имя создаваемой для модели коллекции(Mongoose создаст коллекцию для модели *SomeModel*), второй аргумент - схема, которая используется для создания модели.

**Примечание:** После создания классов модели они могут применяться для создания, обновления или удаления записей в базе, для выполнения запросов по всем записям или по их подмножествам. Как это делать, будет показано в разделе Использование моделей, и когда будут создаваться представления.

#### Типы схемы (поля)

Схема может содержать любое количество полей, причём каждое поле будет полем документа, хранимого в БД *MongoDB*. Схема-пример содержит определения многих широко используемых типов полей.

```js
var schema = new Schema({
  name: String,
  binary: Buffer,
  living: Boolean,
  updated: { type: Date, default: Date.now },
  age: { type: Number, min: 18, max: 65, required: true },
  mixed: Schema.Types.Mixed,
  \_someId: Schema.Types.ObjectId,
  array: [],
  ofString: [String], // You can also have an array of each of the other types too.
  nested: { stuff: { type: String, lowercase: true, trim: true } },
});
```

Большинство типов в SchemaTypes (указаны после "type:" или после имён полей) достаточно очевидны. Исключения:

* `ObjectId`: Представляет отдельный экземпляр модели в БД. Например, book может ссылаться на объект- автора. Поле будет содержать уникальный идентификатор (`_id`) отдельного объекта. При необходимости использования этой информации применяют метод `populate()`.
* Mixed: Произвольный тип в схеме.
* []: Массив элементов. В таких моделях можно выполнять JavaScript-операции для массивов (push, pop, unshift, etc.). Выше показан пример массива объектов неопределённого типа и массив строк, но можно использовать массив объектов любого типа.

Код содержит также два способа объявления полей:

* *Имя* и *тип* поля как пара "ключ-значение" (поля `name`, `binary и` `living`).
* *Имя* поля, после которого указывается объект, определяющий *тип* и другие возможности поля, такие как:
    + значения по умолчанию.
    + встроенные валидаторы (например, значения max и min) и функции-валидаторы пользователя.
    + Является ли поле обязательным
    + Должны ли строковые поля автоматически преобразовываться в нижний или верхний регистр, удалять ли ведущие и хвостовые пробелы (`пример:` `{ type: String, lowercase: true, trim: true }`)

Дополнительная информация - в SchemaTypes (документация Mongoose).

#### Валидация (проверка допустимости)

Mongoose предусматривает встроенные валидаторы, валидаторы пользователя, синхронные и асинхронные валидаторы. Во всех случаях можно задать допустимые диапазоны или значения, а также сообщения об ошибках при нарушении условий валидации.

Встроенные валидаторы включают:

* Все SchemaTypes имеют встроенный валидатор required, который определяет, должно ли поле быть заданным перед сохранением документа.
* Числа имеют валидаторы min и max.
* Строки имеют:
    + enum (перечисления): задают множество допустимых для поля значений.
    + match (соответствия)): задают регулярное выражение, которому должна соответствовать строка.
    + maxlength, minlength -максимальная и минимальная длина строки.

Пример ниже (с небольшими изменениями из документации Mongoose) показывает, как задать некоторые валидаторы и сообщения об ошибках:

```js
    var breakfastSchema = new Schema({
      eggs: {
        type: Number,
        min: [6, 'Too few eggs'],
        max: 12
        required: [true, 'Why no eggs?']
      },
      drink: {
        type: String,
        enum: ['Coffee', 'Tea', 'Water',]
      }
    });
```

Подробная информация по валидации полей - в разделе Validation (документация Mongoose).

#### Виртуальные свойства

Виртуальные свойства - это свойства документа, которые можно читать (get) и задавать (set), но которые не хранятся в MongoDB. Методы "геттеры" полезны для форматирования и соединения полей, а "сеттеры" применяют для декомпозиции отдельных значений на несколько частей перед сохранением в БД. Пример из документации собирает (и разбирает) виртуальное свойство "полное имя" из полей "имя" и "фамилия", что удобнее, чем конструировать полное имя каждый раз, когда оно используется в шаблоне.

**Примечание:** В библиотеке виртуальное свойство будет применено для определения уникального URL каждой записи в модели по пути и по значению `_id` записи.

Подробная информация - в разделе Virtuals (документация Mongoose).

#### Методы и помощники запросов

В схеме можно также задать методы экземпляра (instance methods), статические (static) методы и помощники запросов. Статические методы и методы экземпляра аналогичны, но различаются тем, что методы экземпляра связаны с конкретной записью и имеют доступ к текущему объекту. Помощники запросов позволяют расширить API построителя цепочек запросов (например, можно добавить запрос "byName" ("по имени") в дополнение к методам `find()`, `findOne()` и `findById()`).

### Применение моделей

Подготовленную схему можно использовать для создания моделей. Модель представляет коллекцию документов в базе данных, в которой можно выполнять поиск, тогда как экземпляры модели представляют отдельные документы, которые можно сохранять и извлекать.

Ниже предлагается краткий обзор. Более подробно смотрите в Models (документация Mongoose).

#### Создание и изменение документов

Чтобы создать запись, следует определить экземпляр модели и вызвать метод `save()`. В примере ниже SomeModel — это модель с единственным полем "name", которую мы создадим из нашей схемы.

```js
// Создать экземпляр модели SomeModel
var awesome_instance = new SomeModel({ name: "awesome" });

// Сохранить новый экземпляр, передав callback
awesome_instance.save(function (err) {
  if (err) return handleError(err);
  // сохранили!
});
```

Создание записей (а также обновления, удаления и запросы) - это асинхронные операции, поэтому следует предусмотреть колбэк-функцию, которая будет вызвана при завершении операции. В API используется соглашение о первом аргументе, согласно которому первый аргумент колбэк-функции должен быть значением ошибки (или null). Если API возвращает некоторый результат, он должен быть вторым аргументом.

Можно использовать метод `create()` для создании экземпляра модели при его сохранении. Тогда колбэк-функция вернёт ошибку (или null) как первый аргумент и только что созданный экземпляр как второй аргумент.

```js
SomeModel.create({ name: "also\_awesome" }, function (err, awesome\_instance) {
  if (err) return handleError(err);
  // сохранили!
});
```

Каждая модель ассоциирована с соединением (с соединением по умолчанию, если используется `mongoose.model()`). Следует создать новое соединение и вызвать для него `.model()`, чтобы создать документ в другой базе данных.

Поля в новой записи могут быть получены и изменены с применением dot (точка)-синтаксиса. Для сохранения изменений служат методы `save()` и `update()`.

```js
// Доступ к полям модели в dot-нотации
console.log(awesome_instance.name); //вывод в консоль 'also\_awesome'

// Изменить запись, модифицируя поля, потом вызвать save().
awesome_instance.name = "New cool name";
awesome_instance.save(function (err) {
  if (err) return handleError(err); // сохранили!
});
```

#### Поиск записей

При поиске записей методами запросов, условия поиска следует задавать как документ JSON. Приведённый фрагмент кода (ниже) показывает, как в БД найти имена (*name*) и возраст (*age*) всех спортсменов-теннисистов. Соответствие будет определяться по одному полю (sport), но можно добавить критерии поиска, задав, например, регулярное выражение, или удалить все критерии, чтобы получить список всех спортсменов.

```js
var Athlete = mongoose.model("Athlete", yourSchema);

// найти всех теннисистов, выбирать поля 'name' и 'age'
Athlete.find({ sport: "Tennis" }, "name age", function (err, athletes) {
  if (err) return handleError(err);
  // 'athletes' содержит список спортсменов, соответствующих критерию.
});
```

Если задать колбэк-функцию так, как показано выше, запрос будет выполнен немедленно. Однако колбэк-функция будет вызвана только после завершения поиска.

**Примечание:** Все колбэк-функции в Mongoose используют образец `callback(error, result)`. Если при выполнении запроса возникает ошибка, параметр `error` будет содержать объект error, а `result` будет null. При успешном запросе параметр `error` будет null, а `result` будет содержать результат запроса.

Если не задать колбэк-функцию, API вернёт переменную типа Query. Можно использовать объект запроса, чтобы создать и выполнить свой запрос (с колбэк-функцией) позже, при помощи метода `exec()`.

```js
// найти всех теннисистов
var query = Athlete.find({ sport: "Tennis" });

// выбрать поля 'name' и 'age'
query.select("name age");

// ограничить результат 5 элементами
query.limit(5);

// сортировать по возрасту
query.sort({ age: -1 });

// выполнить запрос позже
query.exec(function (err, athletes) {
  if (err) return handleError(err);
  // athletes содержит упорядоченный список из 5 теннисистов
});
```

Выше условия поиска были заданы в методе `find()`. Можно также использовать функцию `where()`, кроме того, можно соединить все части в одном запросе применением оператора dot (.) вместо того, чтобы выполнять их раздельно. Фрагмент кода (см. ниже) выполняет тот же запрос, что и предыдущий фрагмент, но с дополнительным условием для возраста.
```

Athlete.
  find().
  where('sport').equals('Tennis').
  where('age').gt(17).lt(50).  //Дополнительное условие
  limit(5).
  sort({ age: -1 }).
  select('name age').
  exec(callback); // callback - имя нашей колбэк-функции.
```

Метод find() находит все записи, удовлетворяющие условию, но часто требуется найти только одну из таких записей. Вот методы для поиска одной записи:

* `findById()`: Находит документ по заданному идентификатору `id` (каждый документ имеет уникальный идентификатор `id`).
* `findOne()`: Находит один документ, удовлетворяющий заданному критерию.
* `findByIdAndRemove()`, `findByIdAndUpdate()`, `findOneAndRemove()`, `findOneAndUpdate()`: Находит один документ по `id` или по критерию, а затем или обновляет, или удаляет его. Эти методы весьма полезны для обновления или удаления записей.

**Примечание:** Есть также метод `count()`, который определяет количество записей, соответствующих условию. Он полезен при выполнении подсчётов без фактического извлечения записей.

Запросы полезны и во многих других случаях. Дополнительная информация - в Queries (документация Mongoose).

#### Работа со связанными документами — загрузка

Один документ (экземпляр модели) может ссылаться на другой документ при помощи поля `ObjectId` схемы, или на много других документов, используя массив идентификаторов `ObjectIds`. Идентификатор соответствующей модели хранится в поле. При необходимости получить действительное содержимое связанного документа, следует использовать в запросе метод `populate()`, который заменит идентификатор в запросе действительными данными.

Например, в следующей схеме определены авторы и рассказы. У каждого автора может быть несколько рассказов, которые представим массивом ссылок of `ObjectId`. У каждого рассказа может быть только один автор. Ссылка "ref" (выделена жирным) указывает в схеме, какая модель должна быть связана с этим полем.

```js
var mongoose = require("mongoose"),
  Schema = mongoose.Schema;

var authorSchema = Schema({
  name: String,
  stories: [{ type: Schema.Types.ObjectId, ref: "Story" }],
});

var storySchema = Schema({
  author: { type: Schema.Types.ObjectId, ref: "Author" },
  title: String,
});

var Story = mongoose.model("Story", storySchema);
var Author = mongoose.model("Author", authorSchema);
```

Можно сохранить ссылки в связанном документе, используя значение идентификатора `_id`. Ниже создаётся автор, затем рассказ, и значение идентификатора id автора сохраняется в поле "author" рассказа.

```js
var bob = new Author({ name: "Bob Smith" });

bob.save(function (err) {
  if (err) return handleError(err);

  //автор Bob создан, создаём рассказ
  var story = new Story({
    title: "Bob goes sledding",
    author: bob._id, // присваиваем полю значение идентификатора Боба. Идентификатор создаётся по умолчанию!
  });

  story.save(function (err) {
    if (err) return handleError(err);
    // У Боба теперь есть рассказ!
  });
});
```

Теперь документ "story" ссылается на автора по идентификатору документа "author". Для получения информации об авторе применяется метод `populate()` (показано ниже).

```js
Story.findOne({ title: "Bob goes sledding" })
  .populate("author") //подменяет идентификатор автора информацией об авторе!
  .exec(function (err, story) {
    if (err) return handleError(err);
    console.log("The author is %s", story.author.name);
    // выводит "The author is Bob Smith"
  });
```

**Примечание:** Внимательные читатели заметили, что автор добавлен к рассказу, но ничего не сделано, чтобы добавить рассказ к массиву рассказов `stories` автора. Как же тогда получить список всех рассказов конкретного автора? Один из возможных вариантов - добавить автора в массив рассказов, но при этом пришлось бы хранить данные об авторах и рассказах в двух местах и поддерживать их актуальность.

Лучше получить `_id` нашего автора *author*, и применить `find()` для поиска этого идентификатора в поле "author" всех рассказов.

```js
Story.find({ author: bob._id }).exec(function (err, stories) {
  if (err) return handleError(err);
  // возвращает все рассказы, у которых идентификатор Боба.
});
```

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

### Одна схема (модель) - один файл

Можно использовать любую структуру файлов при создании схем и моделей, однако мы настоятельно рекомендуем определять каждую схему модели в отдельном модуле (файле), экспортируя метод для создания модели. Пример приведён ниже:

```js
// Файл: ./models/somemodel.js

//Требуется Mongoose
var mongoose = require("mongoose");

//Определяем схему
var Schema = mongoose.Schema;

var SomeModelSchema = new Schema({
  a\_string: String,
  a\_date: Date,
});

//экспортируется функция для содания класса модели "SomeModel"
module.exports = mongoose.model("SomeModel", SomeModelSchema);
```

You can then require and use the model immediately in other files. Below we show how you might use it to get all instances of the model.

```js
//Создаём модель SomeModel просто вызовом модуля из файла
var SomeModel = require("../models/somemodel");

// Используем объект SomeModel (модель) для поиска всех записей в SomeModel
SomeModel.find(callback_function);
```

Установка базы данных MongoDB
-----------------------------

Мы уже немного понимаем, что может делать Mongoose и как следует проектировать модели. Теперь самое время начать работу над сайтом *LocalLibrary*. Самое первое, что мы должны сделать - установить базу данных MongoDb, в которой будут храниться данные нашей библиотеки.

В этом руководстве мы будем использовать базу данных в "песочнице" ("sandbox") - бесплатный облачный сервис, предоставляемый mLab. Такая база не очень подходит для промышленных веб-сайтов, поскольку не имеет избыточности, но она очень удобна для разработки и прототипирования. Мы используем её, так как она бесплатна, её легко установить, и потому что mLab - популярный поставщик *базы данных как сервиса,* и это может быть разумным выбором для промышленной базы данных (на данный момент другие известные возможности включают Compose, ScaleGrid и MongoDB Atlas).

**Примечание:** При желании можно установить БД MongoDb локально, загрузив и установив подходящие для вашей системы двоичные файлы. В этом случае приводимые ниже инструкции не изменятся, за исключением URL базы данных, который нужно будет задать для установки соединения.

Первым делом надо создать аккаунт на mLab (это бесплатно, требует только основных контактных данных и ознакомления с условиями обслуживания).

После входа в систему вы увидите главную страницу home:

1. Щёлкните **Create New** в разделе *MongoDB Deployments* для создания новой БД.
 ![](/ru/docs/Learn/Server-side/Express_Nodejs/mongoose/mlabcreatenewdeployment.png)
2. Откроется экран *Cloud Provider Selection - раздела провайдера облака*.

 ![MLab - screen for new deployment](/ru/docs/Learn/Server-side/Express_Nodejs/mongoose/mlab_new_deployment_form_v2.png)
    * Выберите план SANDBOX (Free) из раздела Plan Type (тип плана).
    * Выберите любого провайдера в разделе *Cloud Provider (провайдер облака)*. Разные провайдеры обслуживают разные регионы (показаны под выбранным типом плана).
    * Щёлкните кнопку **Continue**.
3. Откроется экран выбора региона *Select Region*.

 ![Select new region screen](/ru/docs/Learn/Server-side/Express_Nodejs/mongoose/mlab_new_deployment_select_region_v2.png)
    * Выберите ближайший к вам регион и щёлкните кнопку **Continue**.
4. Откроется экран *Final Details* для ввода названия БД.
    * Введите имя новой базы - `local_library` и нажмите **Continue**.
5. Откроется экран подтверждения заказа *Order Confirmation*.

 ![Order confirmation screen](/ru/docs/Learn/Server-side/Express_Nodejs/mongoose/mlab_new_deployment_order_confirmation.png)
    * Щёлкните **Submit Order** (подтвердить заказ), чтобы создать БД.
6. Вы вернётесь на главный (home) экран. Щёлкните по вновь созданной базе, чтобы открыть экран с детальной информацией. Как видно, в БД нет коллекций (данных).

 ![mLab - Database details screen](/ru/docs/Learn/Server-side/Express_Nodejs/mongoose/mlab_new_deployment_database_details.png)
 На форме выше обведён URL для соединения с вашей БДthat you need to use to access your database is displayed on the form above (shown for this database circled above). Чтобы его использовать, необходимо создать пользователя БД, который позже введёт этот URL.
7. Щёлкните по вкладке **Users** и выберите кнопку **Add database user** (добавить пользователя БД).
8. Введите имя пользователя и пароль (дважды), затем нажмите **Create** (создать). Не отмечайте *Make read only* (только для чтения)!

 ![](/ru/docs/Learn/Server-side/Express_Nodejs/mongoose/mlab_database_users.png)

Теперь БД создана, и для доступа к ней есть URL, имя пользователя и пароль. Это должно выглядеть примерно так: `mongodb://your_user_namer:your_password@ds119748.mlab.com:19748/local_library`.

Установка Mongoose
------------------

Откройте окно команд и перейдите в каталог, в котором создан каркас веб-сайта Local Library. Введите команду install, чтобы установить Mongoose (и её зависимости), а также добавьте её в файл **package.json**, если вы ещё не сделали этого ранее, при чтении Учебника по Mongoose.

```bash
npm install mongoose
```

Подключение к MongoDB
---------------------

Откройте **/app.js** (в корне проекта) и скопируйте приведённый ниже текст, в котором объявляется *объект приложения* *Express* (после строки `var app = express();`). Замените строку url БД ('*insert\_your\_database\_url\_here*') тем URL, который представляет вашу БД (т.е. используйте информацию, полученную от mLab).

```js
//Устанавливаем соединение с mongoose
var mongoose = require("mongoose");
var mongoDB = "insert\_your\_database\_url\_here"; //замените url!!!
mongoose.connect(mongoDB);
mongoose.Promise = global.Promise;
var db = mongoose.connection;
db.on("error", console.error.bind(console, "MongoDB connection error:"));
```

Как указано ранее в Учебнике по Mongoose, этот код задаёт соединение по умолчанию с привязкой события ошибки error (так что ошибки будут выведены в консоль).

Определение схемы LocalLibrary
------------------------------

Мы определим отдельный модуль для каждой модели как уже обсуждалось выше. Начнём с создания каталога для моделей в корне проекта (**/models**), после чего создадим отдельные файлы для каждой модели:
```

/express-locallibrary-tutorial  //the project root
  /models
    author.js
    book.js
    bookinstance.js
    genre.js
```

### Модель автора Author

Скопируйте код схемы автора `Author` (приведён ниже) в файл **./models/author.js** . В схеме определено, что у автора есть обязательные поля имени и фамилии типа `String` длиной не более 100 символов, и поля типа `Date` дата рождения и дата смерти.

```js
var mongoose = require("mongoose");

var Schema = mongoose.Schema;

var AuthorSchema = new Schema({
  first\_name: { type: String, required: true, max: 100 },
  family\_name: { type: String, required: true, max: 100 },
  date\_of\_birth: { type: Date },
  date\_of\_death: { type: Date },
});

// Виртуальное свойство для полного имени автора
AuthorSchema.virtual("name").get(function () {
  return this.family_name + ", " + this.first_name;
});

// Виртуальное свойство - URL автора
AuthorSchema.virtual("url").get(function () {
  return "/catalog/author/" + this._id;
});

//Export model
module.exports = mongoose.model("Author", AuthorSchema);
```

Мы объявим также в схеме AuthorSchema виртуальное свойство "url" , которое позволит получить абсолютный URL конкретного экземпляра модели — используем это свойство в шаблонах, если потребуется получить связь с конкретным автором.

**Примечание:** Объявить в схеме URL как виртуальные свойства - хорошая идея, т.к. URL отдельного элемента при необходимости изменения требует коррекции только в одном месте.
 Сейчас связь при помощи этого URL ещё не работает, так как у нас ещё нет кода, поддерживающего маршруты для экземпляров модели. Мы построим его в следующей статье!

В конце модуля экспортируется модель.

### Модель книги Book

Скопируйте код схемы `Book` (приведён ниже) в файл **./models/book.js**. Большая часть кода подобна коду для модели автора — объявляется схема с рядом строковых полей, с виртуальным свойством URL для получения URL конкретных книг, затем модель экспортируется.

```js
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 book's URL
BookSchema.virtual("url").get(function () {
  return "/catalog/book/" + this._id;
});

//Export model
module.exports = mongoose.model("Book", BookSchema);
```

Основное отличие в том, что созданы две ссылки на другие модели:

* author - это ссылка на единственный объект модели `Author` , обязательный элемент.
* genre (жанр) - ссылка на массив объектов модели `Genre`. Эта модель ещё не объявлена!
### Модель экземпляра книги BookInstance

Наконец, скопируйте код схемы `BookInstance` (приведён ниже) в файл **./models/bookinstance.js**. Схема `BookInstance` представляет конкретный экземпляр книги, которую можно одолжить на время, и содержит информацию о доступности экземпляров книги, о дате возврата одолженной книги, о деталях версии или печатного экземпляра.

```js
var mongoose = require("mongoose");

var Schema = mongoose.Schema;

var BookInstanceSchema = new Schema({
  book: { type: Schema.ObjectId, ref: "Book", required: true }, //ссылка на книгу
  imprint: { type: String, required: true },
  status: {
    type: String,
    required: true,
    enum: ["Available", "Maintenance", "Loaned", "Reserved"],
    default: "Maintenance",
  },
  due\_back: { type: Date, default: Date.now },
});

// Virtual for bookinstance's URL
BookInstanceSchema.virtual("url").get(function () {
  return "/catalog/bookinstance/" + this._id;
});

//Export model
module.exports = mongoose.model("BookInstance", BookInstanceSchema);
```

В этой схеме новыми являются опции поля:

* `enum`: Позволяет указать допустимые значения строки. В нашем случае используются, чтобы задать статус доступности книги (применение enum (перечисления) означает, что мы ходим предотвратить ошибочное написание и произвольные значения статуса)
* `default`: определяет значение статуса по умолчанию (maintenance) при создании экземпляра книги, и дату `due_back` возврата книги (`now,` сейчас). Отметьте, как используется функция Date при установке даты!

Все остальное знакомо по предыдущим схемам.

### Модель жанра Genre - проверьте себя!

Откройте файл **./models/genre.js** и создайте схему для хранения жанра (категории книги, т.е. художественная или научная, романтика или военная история и т.д.).

Определение будет подобно другим моделям:

* В модели должно быть поле `name` типа `String` для указания жанра.
* Это поле должно быть обязательным, допустимый размер - от 3 до 100 символов.
* Объявите виртуальное (virtual) свойство с именем `url` для URL жанра.
* Экспортируйте модель.
Тестирование — создаём элементы БД
----------------------------------

Вот так. У нас теперь есть все модели для создания сайта!

Для тестирования моделей (и для создания примеров книг и других элементов, которые потребуются в следующих статьях) выполним *независимый* скрипт, который создаст элементы каждого типа:

1. Загрузите (или создайте) файл populatedb.js в каталоге *express-locallibrary-tutorial* (на том же уровне, что и `package.json`).

**Примечание:** Не обязательно понимать, как работает populatedb.js; он просто помещает некоторые данные в базу данных.
2. Введите в корне проекта команду для установки модуля *async,* который потребуется скрипту populatedb.js (роль async обсудим в следующих руководствах)

```bash
npm install async
```

3. Запустите скрипт из командной строки, используя node. В качестве параметра укажите URL вашей БД *MongoDB* (тот самый, которым вы ранее заменили *insert\_your\_database\_url\_here* в файле `app.js` ):

```bash
node populatedb <your mongodb url>
```

4. Скрипт должен выполниться до конца, выводя в терминал создаваемые элементы.

**Примечание:** Откройте свою базу на Lab. Вы сможете увидеть коллекции Book, Author, Genre, BookInstance (книги, авторы, жанры, экземпляры книг) и просмотреть содержащиеся в них документы.

Итог
----

В этой статье мы познакомились с БД и ОРМ (объектно-реляционными моделями) в системе Node/Express, узнали, как определяются схемы и модели Mongoose. Мы применили эти знания при проектировании и реализации моделей `Book`, `BookInstance`, `Author` и `Genre` для веб-сайта *LocalLibrary*.

В конце мы испытали свои модели путём создания ряда элементов (при помощи автономного скрипта). В следующей статье мы рассмотрим создание страниц, на которых будут показаны эти элементы.

Смотрите также
--------------

* Database integration Интеграция БД (документация Express)
* Mongoose website Веб-сайт Mongoose (документация Mongoose)
* Mongoose Guide Справочник Mongoose (документация Mongoose)
* Validation Валидация (документация Mongoose)
* Schema Types Типы в схемах (документация Mongoose)
* Models Модели (документация Mongoose)
* Queries Запросы (документация Mongoose)
* Population Пополнение БД (документация Mongoose)
* Назад
* Обзор: Express Nodejs
* Далее
In this module
--------------

* Express/Node introduction
* Setting up a Node (Express) development environment
* Express Tutorial: The Local Library website
* Express Tutorial Part 2: Creating a skeleton website
* Express Tutorial Part 3: Using a Database (with Mongoose)
* Express Tutorial Part 4: Routes and controllers
* Express Tutorial Part 5: Displaying library data
* Express Tutorial Part 6: Working with forms
* Express Tutorial Part 7: Deploying to production (en-US)


Учебник Express: сайт Local Library - Изучение веб-разработки

Учебник Express: сайт Local Library
===================================

* Назад
* Обзор: Express Nodejs
* Далее

Первая статья в нашей серии практических уроков объясняет, что вы будете изучать, и предоставит обзор сайта "локальной библиотеки" ("local library"), над которым мы будем работать и развивать в последующих статьях.

| Необходимые знания: | Прочтите Введение в Express. Для следования статьям вам также надо будет установить среду разработки Node. |
| --- | --- |
| Задача: | Представить пример приложения, используемого в этом учебнике, и позволить читателям понять, какие темы будут рассмотрены. |

Обзор
-----

Добро пожаловать в учебник MDN «Local Library» Express (Node), в котором мы разрабатываем веб-сайт, который может использоваться для управления каталогом локальной библиотеки.

В этой серии обучающих статей вы будете:

* Использовать инструмент *Express Application Generator* для создания веб-сайта и скелета приложения.
* Запускать и останавливать веб сервер Node.
* Использовать базу данных для хранения данных вашего приложения.
* Создавать маршруты для запросов различной информации и шаблонов ("представлений") для рендеринга данных в виде HTML для отображения в браузере.
* Работать с формами.
* Развёртывать ваше приложение в производство.

Вы уже имеете знания о некоторых из этих тем и кратко касались других. К концу серии уроков вы должны знать достаточно, чтобы разрабатывать простые приложения Express самостоятельно.

Сайт LocalLibrary
-----------------

*LocalLibrary* это название сайта который мы будем создавать и развивать в ходе прохождения этого курса уроков. Как и следовало ожидать, цель сайта - предоставить онлайн-каталог для небольшой локальной библиотеки, где пользователи могут просматривать доступные книги и управлять своими учётными записями.

Этот пример был тщательно подобран, потому что он может масштабироваться, чтобы отображать насколько можно много или мало записей, и может использоваться для демонстрации почти любой возможности Express. Что ещё более важно, это позволяет нам обеспечить *управляемый* путь через функциональность, которая вам понадобится на любом веб-сайте:

* В первых учебных статьях мы определим простую библиотеку, доступную *только для просмотра*, которую могут использовать члены библиотеки, чтобы узнать, какие книги доступны. Это позволяет нам исследовать операции, общие для почти каждого сайта: чтение и отображение содержимого из базы данных.
* По мере нашего развития, пример библиотеки, естественно, будет расширяться, чтобы продемонстрировать более продвинутые функции веб-сайта. Например, мы можем расширить библиотеку, чтобы разрешить создание новых книг, и использовать это, чтобы продемонстрировать, как использовать формы, а также поддерживать аутентификацию пользователей.

Несмотря на то, что это очень масштабируемый пример, он называется ***Local**Library,* потому что мы надеемся показать минимальную информацию, которая поможет быстро начать работать с Express. В результате мы будем хранить информацию о книгах, копиях книг, авторов и другой ключевой информации. Однако, мы не будем хранить информацию о других предметах, которые может предоставить библиотека, или предоставить инфраструктуру, необходимую для поддержки нескольких сайтов библиотек или других функций "большой библиотеки".

Я застрял, где я могу посмотреть код?
-------------------------------------

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

Если вы застряли, вы можете найти полностью разработанную версию веб-сайта на Github.

Резюме
------

Теперь, когда вы знаете немного больше о сайте *LocalLIbrary* и о том, что мы будем изучать, пришло время приступить к созданию скелета проекта, который будет использован в нашем сайте.

* Назад
* Обзор: Express Nodejs
* Далее