Автор выбрал фонд Open Internet/Free Speech для получения пожертвования в рамках программы Write for DOnations.
Интернет постоянно меняется, и теперь он может получить функциональные возможности, которые ранее были доступны только непосредственно на мобильных устройствах. Появление в JavaScript инструмента service worker дает вебу такие новые возможности, как выполнение фоновой синхронизации, кеширование оффлайн и отправка push-уведомлений.
Push-уведомления позволяют пользователям принимать новости от мобильных и веб-приложений. Также они позволяют пользователям поддерживать взаимодействие с существующими приложениями, используя персонализированные и релевантный контент.
В этом обучающем руководстве вы настроите приложение Django в Ubuntu 18.04, которое отправляет push-уведомления в случае любой активности, которая требует от пользователя посещения приложения. Для создания этих уведомлений вы будете использовать пакет Django-Webpush и должны будете настроить и зарегистрировать service worker для отображения уведомлений для клиента. Работающее приложение с уведомлениями будет выглядеть следующим образом:
Для прохождения этого обучающего руководства вам потребуется следующее:
pip
и venv
, установленные в соответствии с данными указаниями.djangopush
, созданный в домашней директории и настроенный в соответствии с указаниями руководства по созданию примера проекта Django в Ubuntu 18.04. Обязательно добавьте IP-адрес вашего сервера в директиву ALLOWED_HOSTS
файла settings.py
.Django-Webpush — это пакет, позволяющий разработчикам интегрировать и отправлять push-уведомления в приложения Django. Мы будем использовать этот пакет для запуска и отправки push-уведомлений из нашего приложения. На этом шаге вы установите Django-Webpush и получите ключи добровольной идентификации сервера приложения (Voluntary Application Server Identification, VAPID), которые необходимы для идентификации вашего сервера и обеспечения уникальности каждого запроса.
Вы обязательно должны находиться в директории проекта ~/djangopush
, которая была создана на этапе выполнения предварительных требований:
Активируйте вашу виртуальную среду:
Обновите версию pip
для гарантии ее актуальности:
Установите Django-Webpush:
После установки пакета добавьте его в список приложений в файле settings.py
. Откройте файл settings.py
:
Добавьте webpush
в список INSTALLED_APPS
:
...
INSTALLED_APPS = [
...,
'webpush',
]
...
Сохраните файл и закройте редактор.
Запустите миграцию в приложении для применения изменений, которые вы внесли в схему базы данных:
Вывод будет выглядеть следующим образом при условии успешного выполнения миграции:
OutputOperations to perform:
Apply all migrations: admin, auth, contenttypes, sessions, webpush
Running migrations:
Applying webpush.0001_initial... OK
Следующий шаг по настройке уведомлений — получение ключей VAPID. Эти ключи используются для идентификации сервера приложения и могут применяться для снижения секретности для URL-адресов подписки, поскольку они ограничивают подписку определенным сервером.
Чтобы получить ключи VAPID, перейдите к веб-приложению wep-push-codelab. Здесь вы получите автоматически сгенерированные ключи. Скопируйте закрытые и открытые ключи.
Далее создайте новую запись в файле settings.py
для ваших данных о VAPID. Откройте файл:
Далее добавьте новую директиву с именем WEBPUSH_SETTINGS
с публичными и частными VAPID ключами и ваш адрес электронной почты под AUTH_PASSWORD_VALIDATORS:
Не забудьте заменить значения your_vapid_public_key
, your_vapid_private_key
и admin@example.com
на ваши данные. Ваш адрес электронной почты будет использоваться для отправки вам уведомлений при наличии проблем на сервере push-уведомлений.
Далее мы настроим представления, которые будут отображать домашнюю страницу приложения и запускать отправку push-уведомлений подписавшимся пользователям.
На этом шаге мы настроим базовое представление home
с объектом-ответом HttpResponse
для нашей домашней страницы, а также представление send_push
. Представления — это функции, которые будут возвращать для веб-запросов. Представление send_push
будет использовать библиотеку Django-Webpush для отправки push-уведомлений, которые будут содержать данные, введенные пользователем на домашней странице.
Перейдите в папку ~/djangopush/djangopush
:
Запуск ls
внутри папки будет отображать основные файлы проекта:
Output/__init__.py
/settings.py
/urls.py
/wsgi.py
Файлы в этой папке генерируются автоматически утилитой django-admin
, которую вы использовали для создания вашего проекта в предварительных требованиях. Файл settings.py
содержит конфигурации для всего проекта, такие как установленные приложения и статичный корневой каталог. Файл urls.py
содержит конфигурацию URL для проекта. Здесь вы будете настраивать маршруты согласно созданным вами представлениям.
Создайте в директории ~/djangopush/djangopush
с новый файл именем views.py
, который будет хранить представления для вашего проекта:
Первое представление, которое мы создадим, — это представление home
, которое будет отображать домашнюю страницу, с которой пользователи смогут отправлять push-уведомления. Добавьте в файл следующий код:
Представление home
оформляется с помощью декоратора require_GET
, ограничивающего представление только для запросов GET. Как правило, представление возвращает ответ для каждого поступающего запроса. Это представление возвращает простой HTML тег в качестве ответа.
Далее мы создадим представление send_push
, которое будет обрабатывать отправленные уведомления с помощью пакета django-webpush
. Оно будет ограничено только запросами POST и будет выведено из-под защиты от *межсайтовой подделки запроса *(CSRF). Это позволит протестировать представление с помощью Postman или любой другой службы RESTful. Однако в реальном рабочем проекте вы должны удалить этот декоратор, чтобы защитить ваши представления от CSRF.
Чтобы создать представление send_push
, нужно добавить следующие импорты, чтобы активировать ответы JSON и получить доступ к функции send_user_notification
в библиотеке webpush
:
Далее добавьте декоратор require_POST
, который будет использовать тело запроса, отправленного пользователем, для создания и отправки push-уведомления:
Мы будем использовать два декоратора для представления send_push
: декоратор require_POST
, ограничивающий представление только для запросов POST, и декоратор csrf_exempt
, выводящий представление из-под защиты от CSRF.
Это представление ожидает данные POST и делает следующее: получает body
запроса и с помощью пакета json десериализует документ JSON и получает объект Python, используя json.loads
. json.loads
получает структурированный документ JSON и преобразовывает его в объект Python.
Представление ожидает, что у поля объекта запроса будут три свойства:
head
: заголовок push-уведомления.body
: тело уведомления.id
: id
отправившего запрос пользователя.Если какое-либо из требуемых свойств отсутствует, представление будет возвращать JSONResponse
со статусом 404 “Not Found”. Если пользователь с данным основным ключом существует, представление будет возвращать user
с соответствующим основным ключом, используя функцию get_object_or_404
из библиотеки django.shortcuts
. Если пользователь не существует, функция будет возвращать ошибку 404.
Также представление использует функцию send_user_notification
из библиотеки webpush
. Эта функция принимает три параметра:
User: получатель push-уведомления.
payload
: информация уведомления, которая включает head
и body
уведомления.ttl: максимальное время в секундах, в течение которого уведомление следует хранить, если польз
ователь находится оффлайн.При отсутствии ошибок представление возвращает JSONResponse
со статусом 200 “Success” и объектом данных. При возникновении ошибки KeyError
представление будет возвращать статус 500 “Internal Server Error”. Ошибка KeyError
возникает при отсутствии запрошенного ключа объекта.
На следующем шаге мы создадим соответствующие маршруты URL для представлений, которые мы создали.
Django позволяет создавать URL-адреса, которые будут подключаться к представлениям с помощью модуля Python с именем URLconf
. Этот модуль размечает выражения маршрута URL для функций Python (ваших представлений). Обычно файл конфигурации URL генерируется автоматически при создании проекта. На этом шаге вы будете обновлять этот файл для включения новых маршрутов для представлений, созданных на предыдущем шаге, а также URL-адресов для приложения django-webpush
, которые будут предоставлять конечные точки для подписанных пользователей для push-уведомлений.
Дополнительную информацию о представлениях см. в руководстве Создание представлений Django.
Откройте urls.py
:
Файл будет выглядеть примерно так:
Следующим шагом будет разметка представлений с созданными вами URL-адресами. Во-первых, добавьте импорт include
, чтобы гарантировать, что все маршруты для библиотеки Django-Webpush будут добавляться в ваш проект:
Далее импортируйте представления, которые вы создали на последнем шаге, и обновите список urlpatterns
для разметки представлений:
Здесь список urlpatterns
регистрирует URL-адреса для пакета django-webpush
и сопоставляет представления с URL-адресами /send_push
и /home
.
Давайте проверим представление /home
, чтобы убедиться, что оно работает надлежащим образом. Убедитесь, что вы находитесь в корневой директории проекта:
Запустите ваш сервер с помощью следующей команды:
Перейдите по адресу http://your_server_ip:8000
. Вы должны увидеть следующую домашнюю страницу:
В данный момент вы можете остановить сервер с помощью кнопок CTRL+C
, потому что мы переходим к созданию шаблонов и их отображению в наших представлениях с помощью функции render
.
Движок шаблонов Django позволяет определять отображаемые пользователям слои приложения с помощью шаблонов, которые аналогичны файлам HTML. На этом шаге вы создадите и отобразите шаблон для представления home
.
Создайте папку с именем templates
в корневой директории вашего проекта:
Если вы запустите команду ls
в корневой папке вашего проекта в текущий момент, вывод будет выглядеть примерно так:
Output/djangopush
/templates
db.sqlite3
manage.py
/my_env
Создайте файл home.html
в папке templates
:
Добавьте следующий в файл для создания формы, в которую пользователи смогут вводить информацию для создания push-уведомлений:
body
файла включает в себя форму с двумя полями: элемент input
будет хранить заголовок/название уведомления, а элемент textarea
будет хранить тело уведомления.
В разделе head
в файле есть два тега meta
, которые будут хранить публичный ключ VAPID и идентификатор пользователя. Эти две переменные требуются для регистрации пользователя и отправки ему push-уведомления. Здесь требуется идентификатор пользователя, поскольку вы будете направлять запросы AJAX на сервер, а id
будет использоваться для идентификации пользователя. Если текущий пользователь является зарегистрированным пользователем, шаблон будет создавать тег meta
с его id
в качестве контента.
Следующим шагом нужно указать Django, где нужно хранить ваши шаблоны. Для этого нужно отредактировать файл settings.py
и обновить список TEMPLATES
.
Откройте файл settings.py
:
Добавьте следующие данные в список DIRS
для указания пути к директории шаблонов:
Затем в файле views.py
обновите представление home
для отображения шаблона home.html
. Откройте файл:
Во-первых, добавьте ряд импортов, включая конфигурацию settings
, которая содержит все параметры проекта из файла settings.py
и функцию render
из django.shortcuts
:
Далее удалите первоначальный код, добавленный в представление home
, и добавьте следующие данные, указывающие, как созданный вами шаблон будет отображаться:
Код присваивает значения для следующих переменных:
webpush_settings
: данный параметр присваивает значение атрибута WEBPUSH_SETTINGS
из конфигурации settings
.vapid_key:
этот элемент получает значение VAPID_PUBLIC_KEY
из объекта webpush_settings
для отправки клиенту. Данный публичный ключ сравнивается с закрытым ключом, чтобы убедиться, что клиент с публичным ключом может получать push-сообщения от сервера.user
: эта переменка поступает из входящего запроса. Когда пользователь отправляет запрос на сервер, данные этого пользователя сохраняются в поле user
.Функция render
будет возвращать файл HTML и объект context, содержащий текущего пользователя и публичный ключ VAPID. Здесь требуются три параметра: запрос
, шаблон
для отображения и объект, который содержит переменные, используемые в шаблоне.
После создания нашего шаблона и обновления представления home
мы можем перейти к настройке Django для обслуживания статичных файлов.
Веб-приложения, включая CSS, JavaScript и другие файлы образа, которые Django воспринимает в качестве “статичных файлов”. Django позволяет собирать все статичные файлы из каждого приложения в вашем проекте в одном месте, из которого они будут обслуживаться. Это решение называется django.contrib.staticfiles
. На этом шаге мы обновим наши настройки, чтобы указать Django, где наши статичные файлы будут храниться.
Откройте файл settings.py
:
В файле settings.py
нужно убедиться, что значение STATIC_URL
было определено:
Далее добавьте список директорий с названием STATICFILES_DIRS
, где Django будет искать статичные файлы:
Теперь вы можете добавить STATIC_URL
в список путей, определенных в файле urls.py
.
Откройте файл:
Добавьте следующий код, который будет импортировать конфигурацию static
URL-адресов и обновлять список urlpatterns
. Вспомогательная функция здесь использует свойства STATIC_URL
и STATIC_ROOT
, которые мы предоставили в файле settings.py
для обслуживания статичных файлов проекта:
После настройки параметров статичных файлов мы можем перейти к определению стиля домашней страницы приложения.
После настройки вашего приложения для обслуживания статичных файлов вы можете создать внешнюю таблицу стилей и привязать ее к файлу home.html
для определения стиля домашней страницы. Все ваши статичные файлы будут храниться в директории static
корневой папки вашего проекта.
Создайте папку static
, а внутри папки static
создайте папку css
:
Откройте файл css с именем styles.css
в папке css
:
Добавьте следующие стили для домашней страницы:
После создания таблицы стилей вы можете привязать ее к файлу home.html
, используя теги статичного шаблона. Откройте файл home.html
:
Обновите раздел head
для включения в него ссылки на внешнюю таблицу стилей:
Убедитесь, что вы находитесь в директории основного проекта, и снова запустите ваш сервер для проверки работы:
При посещении http://your_server_ip:8080
страница должна выглядеть следующим образом:
Снова используйте сочетание клавиш
CTRL+C
для остановки сервера.
Теперь, когда вы успешно создали страницу home.html
и добавили для нее таблицу стилей, вы можете оформить для пользователей подписку на push-уведомления, когда бы они ни посетили домашнюю страницу.
Push-уведомления в веб могут уведомлять пользователей о наличии обновлений для приложений, на которые они подписаны, или для напоминания о возможности вспомнить приложение, которое они использовали в прошлом. Они опираются на две технологии, API push и API notifications. Обеим технологиям необходимо наличие service worker.
Push-уведомление отправляется, когда сервер предоставляет информацию для service worker, а service worker использует API уведомлений для отображения этой информации.
Мы будем подписывать наших пользователей на push-уведомления, а затем будем отправлять информацию из подписки на сервер для их регистрации.
В директории static
создайте папку с именем js
:
Создайте файл с именем registerSw.js
:
Добавьте следующий код, который проверяет, поддерживает ли service worker’ы в браузере пользователя, прежде чем пытаться регистрировать service worker:
Во-первых, функция registerSw
проверяет, поддерживает ли браузер service worker’ы, прежде чем регистрировать их. После регистрации она вызывает функцию initializeState
с данными регистрации. Если service worker’ы не поддерживаются в браузере, вызывается функция showNotAllowed
.
Далее добавьте следующий код под функцией registerSw
для проверки того, может ли пользователь получать push-уведомления, прежде чем пытаться подписать их:
Функция initializeState
проверяет следующее:
reg.showNotification
.PushManager
или нет. Если какая-либо из этих проверок не будет пройдена, функция showNotAllowed
вызывается, а подписка отменяется.Функция showNotAllowed
отображает сообщение на кнопке и отключает его, если пользователь не имеет права принимать уведомления. Также она отображает соответствующие сообщения, если пользователь ограничил для приложения отображение уведомлений, либо если браузер не поддерживает push-уведомления.
После того как мы убедимся, что пользователь может получать push-уведомления, следующим шагом будет оформления подписки на уведомления с помощью команды pushManager
. Добавьте следующий код под функцией showNotAllowed
:
Вызов функции pushManager.getSubscription
возвращает данные для активной подписки. При наличии активной подписки функция sendSubData
вызывается, а информация подписки передается в качестве параметра.
При отсутствии активной подписки публичный ключ VAPID, который шифруется с помощью алгоритма Base64, преобразовывается в Uint8Array с помощью функции urlB64TUint8Array
. Затем вызывается функция pushManager.subscribe
с публичным ключом VAPID и значением userVisible
в качестве опции. Вы можете ознакомиться с доступными опциями здесь.
После успешной подписки пользователя следующим шагом будет отправка данных подписки на сервер. Эти данные будут направляться на конечную точку webpush/save_information
, предоставленную пакетом django-webpush
. Добавьте следующий код под функцией subscribe:
Конечной точке save_information
требуется информация о состоянии подписки (subscribe
и unsubscribe
), данные подписки и браузер. Наконец, мы вызываем функцию registerSw()
для запуска процесса подписки пользователя.
Завершенный файл выглядит следующим образом:
Далее добавьте тег script
для файла registerSw.js
в home.html
. Откройте файл:
Добавьте тег script
перед закрывающим тегом элемента body
:
Поскольку service worker еще не существует, если бы вы оставили приложение запущенным или попытались запустить его снова, то увидели бы сообщение об ошибке. Давайте устраним эту проблему с помощью service worker.
Для отображения push-уведомления вам потребуется активный service worker, установленный на домашней странице приложения. Мы создадим service worker, который прослушивает события push
и отображает сообщения при готовности.
Поскольку мы хотим, чтобы service worker покрывал весь домен, нам нужно установить его в корневой директории приложения. В статье о регистрации service worker вы можете подробнее ознакомиться с процессом. Согласно нашему подходу будет создан файл sw.js
в папке templates
, который мы позднее зарегистрируем в качестве представления.
Создайте файл:
Добавьте следующий код, который указывает service worker на необходимость прослушивания push событий:
Service worker следит за наличием push события. В функции обратного вызова данные события
конвертируются в текст. Мы используем строки title
и body
, если в данных события они отсутствуют. Функция showNotification
получает название уведомления, заголовок уведомления для отображения и объект options в качестве параметров. Объект options содержит несколько свойств для настройки визуальных параметров уведомления.
Чтобы service worker мог работать для всего домена, вам потребуется выполнить его установки в корневой директории приложения. Мы будем использовать TemplateView
для предоставления service worker доступа ко всему домену.
Откройте файл urls.py
:
Добавьте новое объявление импорта и путь в список urlpatterns
для создания представления на основе классов:
Представления на основе классов, такие как TemplateView
, позволяют создавать гибкие и доступные для повторного использования представления. В этом случае метод TemplateView.as_view
создает путь для service worker, передав недавно созданный service worker в качестве шаблона и application/x-javascript
в качестве параметра content_type
для шаблона.
Вы уже создали service worker и зарегистрировали его в качестве маршрута. Далее вы настроите форму на домашней странице для отправки push-уведомлений.
Используя форму на домашней странице, пользователи смогут отправлять push-уведомления, пока ваш сервер запущен. Также вы можете отправить push-уведомления с помощью любой службы RESTful, например, Postman. Когда пользователь отправляет push-уведомления из формы на домашней странице, данные будут включать head
и body
, а также id
получателя. Данные должны быть структурированы следующим образом:
Для прослушивания события submit
формы и отправки данных, которые вводит пользователь, на сервер, мы создадим файл site.js
в директории ~/djangopush/static/js
.
Откройте файл:
Во-первых, добавьте прослушивателя событий submit
в форму, что позволит получить значения для вводимых данных в форме и идентификатор пользователя, который хранится в теге meta
вашего шаблона:
Функция pushForm
получает input
, textarea
и button
внутри формы. Также она получает информацию из тега meta
, включая атрибут user_id
и идентификатор пользователя, который хранится в атрибуте content
тега. Получив эту информацию, она может отправить запрос POST на конечную точку /send_push
на сервере.
Для отправки запросов на сервер мы будем использовать нативную API Fetch. Мы используем Fetch здесь, поскольку API поддерживается большинством браузеров и не требует для работы внешних библиотек. Под добавленным ранее кодом обновите функцию pushForm
для включения кода для отправки запросов AJAX:
Если три обязательных параметра head,
body
и id
присутствуют, мы отправим запрос и временно отключим кнопку submit.
Завершенный файл выглядит следующим образом:
После этого остается добавить файл site.js
в файл home.html
:
Добавьте тег script
:
В данный момент, если вы оставили приложение запущенным или попытались запустить его снова, то получите ошибку, поскольку service workers может функционировать только на защищенных доменах или в localhost
: На следующем шаге мы будем использовать ngrok для создания безопасного туннеля на нашем веб-сервере.
Service worker’ы требуют наличия защищенных соединений для работы на любом сайте, кроме localhost
, поскольку они не защищены от взлома для последующей фильтрации и подмены ответов. По этой причине мы создадим защищенный туннель для нашего сервера с помощью ngrok.
Откройте второе окно командной строки и убедитесь, что вы находитесь в домашней директории:
Если вы начали работу с чистым сервером на базе Ubuntu 18.04, вам потребуется выполнить установку unzip
:
Загрузите ngrok:
Переместите ngrok
в /usr/local/bin
, чтобы получить доступ к команде ngrok
из командной строки:
В первом окне командной строки убедитесь, что вы находитесь в директории проекта и запустите сервер:
Вы должны были сделать это, прежде чем создать защищенный туннель для вашего приложения.
Во втором окне командной строки перейдите к папке проекта и активируйте виртуальную среду:
Создайте защищенный туннель для вашего приложения:
Вы увидите следующий вывод, который включает информацию о защищенном URL-адресе ngrok:
Outputngrok by @inconshreveable (Ctrl+C to quit)
Session Status online
Session Expires 7 hours, 59 minutes
Version 2.2.8
Region United States (us)
Web Interface http://127.0.0.1:4040
Forwarding http://ngrok_secure_url -> 203.0.113.0:8000
Forwarding https://ngrok_secure_url -> 203.0.113.0:8000
Connections ttl opn rt1 rt5 p50 p90
0 0 0.00 0.00 0.00 0.00
Скопируйте ngrok_secure_url
из вывода консоли. Вы должны будете добавить его в список ALLOWED_HOSTS
в файле settings.py
.
Откройте другое окно командной строки перейдите в папку проекта и активируйте виртуальную среду:
Откройте файл settings.py
:
Обновите список ALLOWED_HOSTS
с защищенным туннелем ngrok:
Перейдите на защищенную страницу администратора для входа: https://ngrok_secure_url/admin/
. Вы увидите экран, который будет выглядеть примерно так:
Введите данные пользователя Django с правами администратора на этом экране. Эта информация должна повторять информацию, которую вы вводили при входе в интерфейс администратора на этапе предварительной подготовки. Теперь вы готовы к отправке push-уведомлений.
Введите https://ngrok_secure_url
в адресной строке браузера. Вы увидите запрос разрешения на отображение уведомлений. Нажмите кнопку Allow (Разрешить), чтобы разрешить отображение push-уведомлений в браузере.
Отправка заполненной формы будет отображать уведомлений примерно следующего вида:
Примечание: убедитесь, что ваш сервер запущен, прежде чем пытаться отправить уведомления.
Если вы получили уведомления, это значит, что приложение работает корректно.
Вы создали веб-приложения, которое отправляет push-уведомления на сервере, и с помощью service workers получает и отображает уведомления. Также вы выполнили действия по получению ключей VAPID, которые требуются для отправки push-уведомлений с сервера приложения.
В этом обучающем руководстве вы научились оформлять подписку пользователя для получения push-уведомлений, устанавливать service worker’ы и отображать push-уведомления с помощью API уведомлений.
Вы можете пойти дальше и настроить уведомления для конкретных областей вашего приложения при нажатии. Исходный код для данного руководства можно найти здесь.
Thanks for learning with the DigitalOcean Community. Check out our offerings for compute, storage, networking, and managed databases.
This textbox defaults to using Markdown to format your answer.
You can type !ref in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!
e