подключить js к flask приложению

Мега-Учебник Flask, Часть XX: Магия JavaScript

(издание 2018)

Miguel Grinberg

подключить js к flask приложению. image loader. подключить js к flask приложению фото. подключить js к flask приложению-image loader. картинка подключить js к flask приложению. картинка image loader.Туда Сюда подключить js к flask приложению. image loader. подключить js к flask приложению фото. подключить js к flask приложению-image loader. картинка подключить js к flask приложению. картинка image loader.

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

Под спойлером приведен список всех статей серии 2018 года.

Примечание 1: Если вы ищете старые версии данного курса, это здесь.

Примечание 2: Если вдруг Вы захотели бы выступить в поддержку моей(Мигеля) работы, или просто не имеете терпения дожидаться статьи неделю, я (Мигель Гринберг)предлагаю полную версию данного руководства(на английском языке) в виде электронной книги или видео. Для получения более подробной информации посетите learn.miguelgrinberg.com.

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

Общая черта пользовательского интерфейса для сайтов социальных сетей, в котором пользователи могут взаимодействовать друг с другом, — это отображение краткой сводки пользователя во всплывающей панели при наведении указателя мыши на имя пользователя в любом месте страницы. Если вы никогда не обращали на это внимание, перейдите в Twitter, Facebook, LinkedIn или любую другую крупную социальную сеть, и когда вы видите имя пользователя, просто оставьте указатель мыши поверх него на пару секунд, чтобы увидеть всплывающее окно. Эта глава будет посвящена созданию этой функции для Microblog, пример работы которой вы можете увидеть на скриншоте ниже:

подключить js к flask приложению. image loader. подключить js к flask приложению фото. подключить js к flask приложению-image loader. картинка подключить js к flask приложению. картинка image loader.

Поддержка на стороне сервера

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

app/main/routes.py: Функция всплывающего окна пользователя.

Этот маршрут будет прикреплен к URL-адресу /user/ /popup и просто загрузит запрошенного пользователя, а затем отобразит шаблон с его данными, который является укороченной версией страницы профиля пользователя:

app/templates/user_popup.html: Шаблон всплывающего окна пользователя.

Код JavaScript, который я напишу в следующих разделах, будет ссылаться на этот маршрут, когда пользователь наведёт указатель мыши на имя пользователя. В ответ сервер вернет содержимое HTML для всплывающего окна, которое затем отобразит клиентскую часть. Когда пользователь переместит мышь, всплывающее окно будет удалено. Звучит просто, не так ли?

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

Введение в Bootstrap Popover Component

В главе 11 я познакомил вас с Bootstrap framework как удобным способом создания красиво отформатированных веб-страниц. До сих пор я использовал только минимальную часть этого фреймворка. Bootstrap поставляется в комплекте со многими общими элементами пользовательского интерфейса, все из которых имеют демонстрации и примеры в документации Bootstrap на https://getbootstrap.com. Одним из таких компонентов является Popover, который описан в документации как «небольшой накладной контент, для размещения дополнительной информации». Именно то, что мне нужно!

Большинство компонентов bootstrap определяются с помощью разметки HTML, которая ссылается на определения CSS Bootstrap, которые добавляют стиль форматирования. Некоторые из самых продвинутых также требуют JavaScript. Стандартный способ, которым приложение включает эти компоненты на веб-странице, — это добавление HTML в нужном месте, а затем для компонентов, которые нуждаются в поддержке сценариев, вызов функции JavaScript, которая инициализирует или активирует ее. Компонент popover требует поддержки JavaScript.

Часть HTML для создания popover очень проста, вам просто нужно определить элемент, который будет вызывать появление popover. В моем случае это будет кликабельное имя пользователя, которое появляется в каждом сообщении блога. В sub-шаблоне app/templates/_post.html имя пользователя уже определено:

Теперь в соответствии с документацией popover мне нужно вызвать JavaScript-функцию popover() для каждой ссылки, подобной приведенной выше на странице, и это приведет к инициализации всплывающего окна. Вызов инициализации принимает несколько параметров, которые настраивают всплывающее окно, включая параметры, которые передают содержимое для отображения во всплывающем окне, какой метод использовать, чтобы вызвать всплывающее окно для появления или исчезновения (щелчок, зависание над элементом и т.д. ), если содержимое представляет собой простой текст или HTML, и еще несколько параметров, которые вы можете увидеть на странице документации. К сожалению, после прочтения этой информации у меня появилось больше вопросов, чем ответов, потому, похоже, что этот компонент не предназначен для работы так, как мне это нужно. Ниже приведен список проблем, которые мне потребуется решить для реализации этой функции:

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

Выполнение функции при загрузке страницы

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

app/templates/base.html: Запуск функции после загрузки страницы.

Как видите, я добавил функцию start up в элемент

Источник

Пишем одностраничное приложение с Flask и Vue.js

Авторизуйтесь

Пишем одностраничное приложение с Flask и Vue.js

подключить js к flask приложению. flask vue. подключить js к flask приложению фото. подключить js к flask приложению-flask vue. картинка подключить js к flask приложению. картинка flask vue.

Эта статья — пошаговое руководство по настройке базового CRUD-приложения с помощью Vue и Flask. Начнём с создания нового приложения Vue, используя Vue CLI, а затем перейдём к выполнению основных операций CRUD с помощью RESTful API на бэкенде под управлением Python и Flask.

подключить js к flask приложению. final. подключить js к flask приложению фото. подключить js к flask приложению-final. картинка подключить js к flask приложению. картинка final.

К концу этого урока вы узнаете:

Что такое Flask?

Flask — это простой, но мощный микро-фреймворк для Python, идеально подходящий для создания RESTful API. Как Sinatra (Ruby) и Express (Node), он минималистичен и гибок, поэтому вы можете начинать с простых проектов и при необходимости создавать более сложные приложения.

Если вы первый раз работаете с Flask, вам стоит изучить следующие ресурсы:

Что такое Vue?

Vue — это JavaScript-фреймворк с открытым исходным кодом. Используется для создания пользовательских интерфейсов. Он содержит некоторые из лучших концепций React и Angular, но по сравнению с ними он более доступен, поэтому новички могут быстро приступать к работе. Также он не уступает этим фреймворкам в мощности и предоставляет все необходимые функции для создания современных фронтенд-приложений.

25–27 ноября, Онлайн, Беcплатно

Чтобы узнать больше о Vue, а также о плюсах и минусах его использования по сравнению с Angular и React, можете посмотреть следующие статьи:

Если вы первый раз работаете с Vue, вам следует прочитать введение из официального руководства Vue.

Настройка Flask

Начнём с создания новой директории проекта:

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

Установите Flask вместе с расширением Flask-CORS:

Добавьте файл app.py в только что созданный каталог:

Flask-CORS нужен для отправки cross-origin-запросов (запросы, исходящие из другого протокола, IP-адреса, имени домена или порта), поэтому необходимо включить общий доступ к ресурсам (CORS).

Стоит отметить, что описанная выше настройка позволяет отправлять запросы из разных источников по всем маршрутам из любого домена, протокола или порта. В продакшне должны быть разрешены только запросы из домена, на котором размещено фронтенд-приложение. Для получения дополнительной информации можете ознакомиться с документацией Flask-CORS.

Для проверки введите в строку адреса браузера http://localhost:5000/ping. Должно получиться: « Pong! ».

Настройка Vue

Для создания индивидуального темплейта проекта используем мощный интерфейс Vue CLI.

Установите его глобально:

Если вы первый раз работаете с npm, вам будет полезно почитать официальное руководство по нему.

В каталоге flask-vue-crud выполните следующую команду для инициализации нового проекта Vue под именем client с конфигом webpack:

webpack — это пакетный модуль и инструмент для сборки, используемый для создания, минимизации и объединения файлов JavaScript и других клиентских ресурсов.

Шаги создания нового проекта Vue:

Должно получиться следующее:

Файл index.html является отправной точкой данного Vue-приложения.

Также обратите внимание на элемент

Файлы и каталоги внутри папки src :

main.js — точка входа в приложение, которая загружает и инициализирует Vue вместе с корневым компонентом.
App.vue — корневой компонент, из которого будут рендериться все остальные компоненты (отправная точка).
assets — место хранения статических ассетов вроде изображений и шрифтов.
components — место хранения UI-компонентов.
router — место определения URL-адресов и сопоставление их с компонентами.

Перейдите по адресу http://localhost:8080 в браузере. Вы должны увидеть следующее:

подключить js к flask приложению. default vue app. подключить js к flask приложению фото. подключить js к flask приложению-default vue app. картинка подключить js к flask приложению. картинка default vue app.

Добавьте новый компонент с именем Ping.vue в папку client/src/components :

Обновите файл client/src/router/index.js так, чтобы он отображал / в компонент Ping:

В client/src/App.vue удалите изображение из темплейта:

Теперь в браузере должно отобразиться « Hello! ».

Чтобы соединить клиентское Vue-приложение с бэкендом на Flask, можно использовать библиотеку axios для отправки AJAX-запросов.

Начнём с установки:

Обновим раздел script компонента в Ping.vue следующим образом:

Запустите приложение Flask в новом окне. В браузере по адресу http://localhost:8080 должно отобразиться « pong! ». По сути, после ответа от серверной части устанавливаем в msg значение, полученное из data вернувшегося объекта.

Настройка Bootstrap

Добавим Bootstrap, чтобы можно было быстро настроить стиль приложения.

Импортируем стили Bootstrap в client/src/main.js :

Обновим раздел style в client/src/App.vue :

Убедитесь, что Bootstrap подключён корректно, используя Button и Container в компоненте Ping :

подключить js к flask приложению. bootstrap. подключить js к flask приложению фото. подключить js к flask приложению-bootstrap. картинка подключить js к flask приложению. картинка bootstrap.

Добавим компонент Books в новый файл Books.vue :

Добавим таблицу в стиле Bootstrap в компонент Books :

Отображаться должно следующее:

подключить js к flask приложению. books component 1. подключить js к flask приложению фото. подключить js к flask приложению-books component 1. картинка подключить js к flask приложению. картинка books component 1.

Теперь можно приступить к созданию функциональности CRUD-приложения.

Что будем создавать?

Цель — разработать бэкенд RESTful API, работающий на Python и Flask, для единственного ресурса — книги. API должен следовать принципам разработки RESTful, используя основные HTTP-команды: GET, POST, PUT и DELETE.

подключить js к flask приложению. final. подключить js к flask приложению фото. подключить js к flask приложению-final. картинка подключить js к flask приложению. картинка final.

GET-маршрут

Сервер

Добавим список книг в server/app.py :

Добавим обработчик маршрута:

Теперь запустим приложение и проверим маршрут по адресу http://localhost:5000/books.

Клиент

После инициализации компонента вызываем метод getBooks() через хук жизненного цикла (lifecycle hook) created, который выбирает книги из только что настроенного маршрута на бэкенде.

Больше информации про Lifecycle Hook находится здесь.

В темплейте просматривается список книг с помощью директивы v-for, которая создаёт новую строку таблицы на каждой итерации. Значение индекса используется в качестве ключа (key). Затем используется директива v-if для отображения Yes или No — читал пользователь книгу или нет.

подключить js к flask приложению. books component 2. подключить js к flask приложению фото. подключить js к flask приложению-books component 2. картинка подключить js к flask приложению. картинка books component 2.

Bootstrap Vue

В следующем разделе используем компонент Modal для добавления новых книг. Для этого добавим библиотеку Bootstrap Vue, которая предоставляет набор Vue-компонентов, стилизованных с помощью HTML и CSS на основе Bootstrap.

Выбор Bootstrap Vue обоснован тем, что компонент Modal Bootstrap использует jQuery. Следует избегать совместного использования jQuery и Vue в одном проекте, поскольку последний использует Virtual Dom для обновления DOM-структуры. Другими словами, если вы используете jQuery для манипуляций с DOM, Vue об этом не узнает. По крайней мере, если вам необходимо использовать jQuery, не используйте его вместе с Vue на одних и тех же элементах DOM.

Подключим библиотеку Bootstrap Vue в файле client/src/main.js :

POST-маршрут

Сервер

Обновим существующий обработчик маршрута для обработки POST-запросов для добавления новых книг:

Запустив сервер Flask, вы можете проверить POST-маршрут на новой вкладке браузера:

Вы также должны увидеть добавленную книгу по http://localhost:5000/books.

Клиент

Внесём следующий modal для добавления новой книги. Начнём с HTML:

Эту часть нужно добавить непосредственно перед закрывающим тегом

Обновим раздел script :

Рассмотрим, что происходит в этом фрагменте кода.

Теперь обновим кнопку «Add Book» в темплейте, чтобы при её нажатии отображался modal:

Теперь компонент должен выглядеть следующим образом:

Можно выполнить проверку, попробовав добавить книгу.

подключить js к flask приложению. add new book. подключить js к flask приложению фото. подключить js к flask приложению-add new book. картинка подключить js к flask приложению. картинка add new book.

Компонент Alert

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

Добавим новый файл с именем Alert.vue в каталог client/src/components :

Затем импортируем его в разделе script компонента Books и зарегистрируем:

Теперь можно ссылаться на новый компонент в разделе template :

Обновите браузер. Должно быть отображено следующее:

подключить js к flask приложению. alert. подключить js к flask приложению фото. подключить js к flask приложению-alert. картинка подключить js к flask приложению. картинка alert.

Теперь добавим фактический компонент b-alert в шаблон:

подключить js к flask приложению. alert 2. подключить js к flask приложению фото. подключить js к flask приложению-alert 2. картинка подключить js к flask приложению. картинка alert 2.

Больше информации о props находится здесь.

Чтобы сделать Alert динамическим и передать пользовательское сообщение, можно использовать выражение привязки (binding expression) в Books.vue :

Добавьте message в параметр data в Books.vue :

Обновим сообщение в addBook :

Добавим showMessage в data :

Теперь можно проверить работу.

подключить js к flask приложению. add new book 2. подключить js к flask приложению фото. подключить js к flask приложению-add new book 2. картинка подключить js к flask приложению. картинка add new book 2.

PUT-маршрут

Сервер

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

Обновим BOOKS в server/app.py :

Также не забудьте импортировать:

Рефакторинг all_books для учёта уникального идентификатора при добавлении новой книги:

Добавим новый обработчик маршрута:

Добавим вспомогательную функцию:

Клиент

Будем идти пошагово:

1. Добавление modal и формы

Сначала добавим новый modal к темплейту, сразу после первого modal:

Добавим стейт формы в часть data раздела script :

2. Обработка нажатия кнопки Update

Обновим кнопку «Update» в таблице:

Добавим новый метод для обновления значений в editForm :

Затем добавим метод, обрабатывающий отправку формы:

3. Подключение AJAX-запроса

4. Оповещение пользователя (Alert)

5. Обработка нажатия кнопки Cancel

Обязательно протестируйте приложение. Убедитесь, что modal отображается при нажатии кнопки и что введённые значения заполнены правильно.

подключить js к flask приложению. update book. подключить js к flask приложению фото. подключить js к flask приложению-update book. картинка подключить js к flask приложению. картинка update book.

DELETE-маршрут

Сервер

Обновим обработчик маршрута:

Клиент

Обновим кнопку «Delete» следующим образом:

Добавим методы для обработки нажатия кнопки, а затем удалим книгу:

подключить js к flask приложению. delete book. подключить js к flask приложению фото. подключить js к flask приложению-delete book. картинка подключить js к flask приложению. картинка delete book.

Заключение

В этой статье были рассмотрены основы настройки CRUD-приложения с помощью Vue и Flask. Исходный код из тега v1 вы можете найти в репозитории flask-vue-crud.

Источник

Создание веб-приложения с помощью Flask в Python 3

Published on May 13, 2020

Автор выбрал фонд Free and Open Source Fund для получения пожертвования в рамках программы Write for DOnations.

Введение

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

В рамках этого обучающего руководства вы будете использовать инструментарий Bootstrap, чтобы сделать ваше приложение визуально привлекательным. Bootstrap поможет вам включить в ваше веб-приложение быстрые веб-страницы, чтобы приложение можно было использовать на мобильных браузерах без написания для этого собственных кодов HTML, CSS и JavaScript. Инструментарий дает возможность изучить работу Flask.

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

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

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

Перед началом выполнения этого руководства вам потребуется:

Шаг 1 — Установка Flask

Если вы еще не активировали среду программирования, убедитесь, что находитесь в директории проекта ( flask_blog ), и с помощью следующей команды активируйте среду:

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

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

Чтобы установить Flask, запустите следующую команду:

После завершения установки запустите следующую команду, чтобы подтвердить установку:

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

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

Шаг 2 — Создание базового приложения

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

В директории flask_blog откройте файл с именем hello.py для редактирования. Используйте nano или любой другой текстовый редактор:

Этот файл hello.py будет служить минимальным примером того, как обрабатывать запросы HTTP. Внутри него импортируйте объект Flask и создайте функцию, которая возвращает ответ HTTP. Напишите следующий код внутри файла hello.py ​​​:

Функция просмотра hello() возвращает строку ‘Hello, World!’ в качестве ответа.

Сохраните и закройте файл.

Для запуска вашего веб-приложения сначала укажите Flask, где искать приложение (в вашем случае файл hello.py ) с помощью переменной среды FLASK_APP :

Затем запустите его в режиме разработки с помощью переменной среды FLASK_ENV :

И наконец, запустите приложение, используя команду flask run :

После запуска приложения вы увидите примерно следующее:

В предыдущем выводе представлена следующая информация:

Откройте браузер и введите URL ​​​​​​ http://127.0.0.1:5000/ ​​​​​​. Вы получите строку Hello, World! в качестве ответа. Это подтверждает то, что ваше приложение успешно работает.

Внимание. Flask использует простой веб-сервер для обслуживания нашего приложения в среде разработки, что также означает, что отладчик Flask работает для облегчения работы по обнаружению ошибок. Этот сервер для разработки не должен использоваться при развертывании в производственной среде. Дополнительную информацию можно найти в документации Flask на странице Опции развертывания или в обучающем руководстве по развертыванию Flask.

Теперь у вас есть небольшое веб-приложение Flask. Вы запустили ваше приложение и вывели информацию в браузере. Далее вы будете использовать файлы HTML в вашем приложении.

Шаг 3 — Использование шаблонов HTML

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

На этом этапе вы создадите свое основное приложение Flask в новом файле.

Функция просмотра index() возвращает результат вызова render_template() с index.html​​ в качестве аргумента. Это дает указание render_template() искать файл с именем index.html в папке шаблонов. И папка, и файл еще отсутствуют. Вы получите сообщение об ошибке, если запустите приложение на этом этапе. Тем не менее при запуске вы уже будете знать об этой часто встречающейся ошибке. Затем вы сможете исправить ошибку, создав необходимые папку и файл.

Сохраните и закройте файл.

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

подключить js к flask приложению. step3a. подключить js к flask приложению фото. подключить js к flask приложению-step3a. картинка подключить js к flask приложению. картинка step3a.

После этого добавьте следующий код HTML внутри index.html ​​:

Сохраните файл и используйте свой браузер для перехода на http://127.0.0.1:5000/ или обновите страницу. Теперь браузер должен отобразить текст Welcome to FlaskBlog в теге

Помимо папки templates веб-приложения Flask также обычно имеют папку static для хостинга статичных файлов, таких как файлы CSS, файлы JavaScript и изображения, которые использует приложение.

После этого откройте файл style.css в директории css для редактирования:

Добавьте следующее правило CSS в файл style.css :

Код CSS добавит границу, изменит цвет на коричневый, выравняет текст по центру и добавит небольшое дополнение к меткам

Сохраните и закройте файл.

Далее откройте файл шаблона index.html для редактирования:

Добавьте ссылку в файл style.css внутри раздела файла шаблона index.html :

Для этого вы используете вспомогательную функцию url_for() ​​​ для генерирования подходящего расположения файла. Первый аргумент указывает, что вы связаны со статичным файлом, а второй — это путь файла внутри статичной директории.

Сохраните и закройте файл.

После обновления страницы индекса вашего приложения вы увидите, что цвет текста Welcome to FlaskBlog ​​​ теперь коричневый, расположен по центру и добавлен внутри границы.

Используйте язык CSS для оформления стиля приложения и придавайте ему более привлекательный вид с помощью своего собственного дизайна. Однако, если вы не веб-дизайнер или не знакомы с CSS, воспользуйтесь инструментарием Bootstrap, который предлагает простые в использовании компоненты для оформления приложения. В данном проекте мы будем использовать Bootstrap.

Для создания базового шаблона сначала необходимо создать файл с именем base.html внутри директории templates :

Введите следующий код в шаблоне base.html ​​:

Сохраните и закройте файл после редактирования.

Источник

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *