В предыдущей части мы настроили структуру приложения, в данной статье мы настроим Strapi API и выведем список ресторанов.
Примечание: исходный код для всей серии статей доступен здесь.
Создаем рестораны
Первым делом нам нужно отобразить список ресторанов в нашем приложении. Разумеется, данным списком мы будем управлять через Strapi API, поэтому давайте его настроим.
Устанавливаем Content Type
Content Type, также называется моделью (model
). Strapi API по умолчанию включает в себя модель user
. Сейчас нам нужны рестораны, поэтому новая модель как вы уже догадываетесь будет называться restaurant
(модели именуются в единственном числе).
Вот что нам нужно сделать:
- Перейти в конструктор моделей http://localhost:1337/admin/plugins/content-type-builder
- Нажать на
Create new content-type
- Установить
restaurant
в качестве имени и нажать кнопку "Continue" - Далее создать следующие поля:
name
с типом Textdescription
с типом Rich Textimage
с типом Media
- Нажать кнопки "Finish" и после "Save"
После этого сервер должен автоматически перезагрузится и новая ссылка Restaurant
появится в левом меню.
Добавляем записи
Отлично! Мы создали первую модель, следующим шагом будет добавление ресторанов в базу данных. Для этого кликните по ссылке Restaurant в левом меню.
Теперь мы находимся в плагине Content Manager
, интерфейс которого позволяет просматривать, изменять и добавлять записи.
- Нажмите на
Add New Restaurant
- Укажите
name
,description
и перетащите картинку в полеimage
- Сохраните
Создайте еще столько ресторанов сколько хотите увидеть в приложении.
Разрешаем доступ
У нас есть записи в базе данных — это хорошо. Однако возможность делать запросы к базе из API еще лучше. Когда мы создали модель restaurant
, под капотом Strapi создал ряд файлов расположенные в api/restaurant
. Эти файлы включают в себя основную логику, предоставляя полностью кастомизируемое CRUD API. Метод для получения ресторанов find
доступен здесь: http://localhost:1337/restaurants.
Попытавшись посетить данный URL, вы будете удивлены увидев 403 ошибку. На самом деле это нормально: новые Strapi API спроектированы такими по умолчанию.
Не волнуйтесь, сделать роут публичным просто и интуитивно понятно:
- Перейдите на вкладку
Roles & Permissions
http://localhost:1337/admin/plugins/users-permissions. - Выберите
Public
- Поставьте галочку в чекбоксах
find
иfindone
секцииRestaurant
- Сохраните
Важно: сделайте тоже самое для роли authenticated
- Перейдите на вкладку
Roles & Permissions
http://localhost:1337/admin/plugins/users-permissions. - Выберите
Authenticated
- Поставьте галочку в чекбоксах
find
иfindone
секцииRestaurant
- Сохраните.
Вернемся назад на http://localhost:1337/restaurants, теперь мы должны увидеть список ресторанов.
Включаем GraphQL
По умолчанию API генерируется в REST формате. Что если я скажу вам, что мы можем его превратить в GraphQL в течении 10 секунд?
Давайте проверим что это так.
Плагин для GraphQL доступен в Strapi, установим его следующей командой в директории /backend
:
yarn strapi install graphql
# или
npm run strapi install graphql
На этом все, с бекендом мы закончили.
- Перезагрузите сервер (
yarn develop
илиnpm run develop
) - Перейдем на http://localhost:1337/graphql и попробуем следующий запрос:
{
restaurants {
id # Или _id если вы используете MongoDB
name
}
}
Если мы увидим список ресторанов, то можно переходить к следующем шагу:
- Установим GraphQL и @nuxt-apollo в нашу
/frontend
директорию
yarn add @nuxtjs/apollo graphql
# или
npm install @nuxtjs/apollo graphql
Модули и настройки для apollo должны быть установлены в nuxt.config.js
:
...
modules: [ '@nuxtjs/apollo',
],
apollo: { clientConfigs: { default: { httpEndpoint: 'http://localhost:1337/graphql' } }
},
...
Показываем рестораны
Пока что мы движемся в правильном направлении. Что делать если мы хотим отобразить рестораны в Nuxt приложении? Давайте поместим необходимые для этого файлы в соответствующие директории.
- Создадим
./pages/restaurants/index.vue
файл и скопируем в него следующий код:
<template>
<div>
// Поиск ресторанов
<form class="uk-search uk-search-large uk-align-center uk-margin">
<span uk-search-icon></span>
<input class="uk-search-input" v-model="query" type="search" placeholder="Search...">
</form>
// Карточки с ресторанами
<div class="uk-card uk-card-default uk-grid-collapse uk-child-width-1-2@m uk-margin" v-for="restaurant in filteredList" v-bind:key="restaurant" uk-grid>
<div class="uk-card-media-left uk-cover-container">
<img :src="'http://localhost:1337/' + restaurant.image.url" alt="" uk-cover>
<canvas width="600" height="400"></canvas>
</div>
<div>
<div class="uk-card-body">
<h3 class="uk-card-title">{{ restaurant.name }}</h3>
<p>{{ restaurant.description }}</p>
// Ссылка на рестораны
<router-link :to="{ name: 'restaurants-id', params: { id: restaurant.id }}" tag="a" class="uk-button uk-button-primary">See dishes
</router-link>
</div>
</div>
</div>
// Если ресторанов не найдено
<div class="uk-container uk-container-center uk-text-center" v-if="filteredList.length == 0">
<img src="https://assets-ouch.icons8.com/preview/19/52de2377-696e-4194-8c63-0a81aef60b4f.png" height="800" width="800">
<p>No restaurants found</p>
</div>
</div>
</template>
<script>
// Импортируем запрос ресторанов
import restaurantsQuery from '~/apollo/queries/restaurant/restaurants'
export default {
data() {
return {
// Инициализируем пустую переменную с ресторанами
restaurants: [],
query: ''
}
},
apollo: {
restaurants: {
prefetch: true,
query: restaurantsQuery
}
},
computed: {
// Ищем рестораны
filteredList() {
return this.restaurants.filter(restaurant => {
return restaurant.name.toLowerCase().includes(this.query.toLowerCase())
})
},
}
}
</script>
Что мы написали?
Две главные части — шаблон и скрипт. Эти составляющие типичны для Vue.js приложений.
Раздел с шаблоном устанавливает структуру страницы, как вы видите некоторые атрибуты специфичны для Vue.js:
v-for
: повторяет тег количество раз равное длине массива (restaurants
в нашем случае).v-if
: отображает тег только если переданное условие валидно.v-model
: связывает переменную со значением инпута. Применяется в данном случае для фильтрации ресторанов по их названию.vue-router
: создает ссылку на страницу.
В скриптовой части мы импортируем необходимые компоненты и модули.
GraphQL запрос
Как вы могли заметить, мы вызываем restaurantsQuery
GraphQL запрос с помощью apollo здесь:
...
apollo: { restaurants: { prefetch: true, query: restaurantsQuery }
},
...
Для этого мы создадим директорию которая содержит запрос к Strapi API.
- Создаем
/frontend/apollo/queries/restaurant/restaurants.gql
и вставляем следующий код:
query Restaurants {
restaurants {
id
name
description
image {
url
}
}
}
Отлично! Теперь мы можем увидеть список ресторанов!
В следующей части вы узнаете как отобразить список блюд.