Le web est en constante évolution, et il peut maintenant réaliser des fonctionnalités qui étaient auparavant uniquement disponibles sur des périphériques mobiles natifs. L’introduction de JavaScript, ouvriers de service a donné le web capacité retrouvée à faire des choses comme contexte de synchronisation, en mode hors connexion mise en cache et l’envoi des notifications push.
Notifications push permettent aux utilisateurs de participer pour recevoir des mises à jour de mobile et d’applications web. Elles permettent également aux utilisateurs de réengager avec les applications existantes à l’aide de contenu personnalisé et pertinent.
Dans ce didacticiel, vous définirez une application Django sur Ubuntu 18.04 qu’envoie push notifications chaque fois qu’il y a une activité qui oblige l’utilisateur à visiter la demande. Pour créer ces notifications, vous utiliserez le paquet de Django-Webpush et mettre en place et s’inscrire à un travailleur de service pour afficher les notifications au client. La demande de travail avec les notifications ressemblera à ceci :
Web push final
Conditions préalables
Avant de commencer ce guide, vous aurez besoin des éléments suivants :
Un serveur Ubuntu 18.04 avec un utilisateur non-root et un pare-feu actif. Vous pouvez suivre les lignes directrices dans le présent guide d’installation du premier serveur pour plus d’informations sur la création d’un serveur Ubuntu 18.04.
pip et venv installé en suivant ces lignes directrices.
Un projet de Django appelé djangopush créé dans votre répertoire home, mis en place suivant ces directives sur la création d’un échantillon de projet Django sur Ubuntu 18.04. N’oubliez pas d’ Ajouter l’adresse IP de votre serveur à la directive ALLOWED_HOSTS dans votre fichier settings.py .
Étape 1 — Installation de Django-Webpush et d’obtenir les clés insipides
Django-Webpush est un package qui permet aux développeurs d’intégrer et d’envoyer des notifications push web dans les applications de Django. Nous allons utiliser ce paquet pour déclencher et envoyer les notifications push de notre application. Dans cette étape, vous installer Django-Webpush et obtenir les clés d’Identification volontaire de serveur Application (VAPID) qui sont nécessaires pour identifier votre serveur et d’assurer l’unicité de chaque demande.
Assurez-vous que vous êtes dans la ~/djangopush répertoire de projet que vous avez créé dans les conditions préalables :
cd ~/djangopush
Activer votre environnement virtuel :
source my_env/bin/activate
Mettre à niveau votre version de pip pour s’assurer que c’est à jour :
pip install –upgrade pip
Installer Django-Webpush :
pip install django-webpush
Après avoir installé le package, ajoutez-le à la liste des applications dans votre fichier settings.py . Premier open settings.py:
nano ~/djangopush/djangopush/settings.py
Ajouter webpush à la liste des INSTALLED_APPS:
~/djangopush/djangopush/Settings.py
…
INSTALLED_APPS = [
…,
‘webpush’,
]
…
Enregistrez le fichier, puis fermez l’éditeur.
Exécutez les migrations sur l’application pour appliquer les modifications que vous avez apportées à votre schéma de base de données :
python manage.py migrate
La sortie ressemble à ceci, ce qui indique une migration réussie :
Output
Operations to perform:
Apply all migrations: admin, auth, contenttypes, sessions, webpush
Running migrations:
Applying webpush.0001_initial… OK
La prochaine étape dans la mise en place des notifications push web devient INSIPIDES clés. Ces touches identifient le serveur d’applications et peuvent être utilisés pour réduire le secret pour pousser abonnement URL, car ils limitent les abonnements sur un serveur spécifique.
Pour obtenir les clés de l’INSIPIDES, accédez à l’application web de wep-push-codelab . Ici, vous recevrez les clés générées automatiquement. Copier les clés publiques et privées.
Ensuite, créez une nouvelle entrée dans settings.py pour votre information insipide. Commencez par ouvrir le fichier :
nano ~/djangopush/djangopush/settings.py
Ensuite, ajoutez une nouvelle directive appelée WEBPUSH_SETTINGS avec vos clés publique et privée INSIPIDES et votre email ci-dessous AUTH_PASSWORD_VALIDATORS:
~/djangopush/djangopush/Settings.py
…
AUTH_PASSWORD_VALIDATORS = [
…
]
WEBPUSH_SETTINGS = {
“VAPID_PUBLIC_KEY”: “your_vapid_public_key”,
“VAPID_PRIVATE_KEY”: “your_vapid_private_key”,
“VAPID_ADMIN_EMAIL”: “[email protected]”
}
# Internationalization
# https://docs.djangoproject.com/en/2.0/topics/i18n/
…
N’oubliez pas de remplacer l’espace réservé de valeurs your_vapid_public_key, your_vapid_private_keyet [email protected] avec vos propres informations. Votre adresse email, c’est comment vous serez informé si le serveur push connaît des problèmes.
Next, we’ll set up views that will display the application’s home page and trigger push notifications to subscribed users.
Step 2 — Setting Up Views
In this step, we’ll setup a basic home view with the HttpResponse response object for our home page, along with a send_push view. Views are functions that return response objects from web requests. The send_push view will use the Django-Webpush library to send push notifications that contain the data entered by a user on the home page.
Navigate to the ~/djangopush/djangopush folder:
cd ~/djangopush/djangopush
Running ls inside the folder will show you the project’s main files:
Output
/__init__.py
/settings.py
/urls.py
/wsgi.py
The files in this folder are auto-generated by the django-admin utility that you used to create your project in the prerequisites. The settings.py file contains project-wide configurations like installed applications and the static root folder. The urls.py file contains the URL configurations for the project. This is where you will set up routes to match your created views.
Create a new file inside the ~/djangopush/djangopush directory called views.py, which will contain the views for your project:
nano ~/djangopush/djangopush/views.py
The first view we’ll make is the home view, which will display the home page where users can send push notifications. Add the following code to the file:
~/djangopush/djangopush/views.py
from django.http.response import HttpResponse
from django.views.decorators.http import require_GET
@require_GET
def home(request):
return HttpResponse(‘
Home Page
‘)
The home view is decorated by the require_GET decorator, which restricts the view to GET requests only. A view typically returns a response for every request made to it. This view returns a simple HTML tag as a response.
The home view is decorated by the require_GET decorator, which restricts the view to GET requests only. A view typically returns a response for every request made to it. This view returns a simple HTML tag as a response.
The next view we’ll create is send_push, which will handle sent push notifications using the django-webpush package. It will be restricted to POST requests only and will be exempted from Cross Site Request Forgery (CSRF) protection. Doing this will allow you to test the view using Postman or any other RESTful service. In production, however, you should remove this decorator to avoid leaving your views vulnerable to CSRF.
To create the send_push view, first add the following imports to enable JSON responses and access the send_user_notification function in the webpush library:
~/djangopush/djangopush/views.py
from django.http.response import JsonResponse, HttpResponse
from django.views.decorators.http import require_GET, require_POST
from django.shortcuts import get_object_or_404
from django.contrib.auth.models import User
from django.views.decorators.csrf import csrf_exempt
from webpush import send_user_notification
import json
Next, add the require_POST decorator, which will use the request body sent by the user to create and trigger a push notification:
~/djangopush/djangopush/views.py
@require_GET
def home(request):
…
@require_POST
@csrf_exempt
def send_push(request):
try:
body = request.body
data = json.loads(body)
if ‘head’ not in data or ‘body’ not in data or ‘id’ not in data:
return JsonResponse(status=400, data={“message”: “Invalid data format”})
user_id = data[‘id’]
user = get_object_or_404(User, pk=user_id)
payload = {‘head’: data[‘head’], ‘body’: data[‘body’]}
send_user_notification(user=user, payload=payload, ttl=1000)
return JsonResponse(status=200, data={“message”: “Web push successful”})
except TypeError:
return JsonResponse(status=500, data={“message”: “An error occurred”})
We are using two decorators for the send_push view: the require_POST decorator, which restricts the view to POST requests only, and the csrf_exempt decorator, which exempts the view from CSRF protection.
This view expects POST data and does the following: it gets the body of the request and, using the json package, deserializes the JSON document to a Python object using json.loads. json.loads takes a structured JSON document and converts it to a Python object.
The view expects the request body object to have three properties:
head: The title of the push notification.
body: The body of the notification.
id: The id of the request user.
If any of the required properties are missing, the view will return a JSONResponse with a 404 “Not Found” status. If the user with the given primary key exists, the view will return the user with the matching primary key using the get_object_or_404 function from the django.shortcuts library. If the user doesn’t exist, the function will return a 404 error.
The view also makes use of the send_user_notification function from the webpush library. This function takes three parameters:
User: The recipient of the push notification.
payload: The notification information, which includes the notification head and body.
ttl: The maximum time in seconds that the notification should be stored if the user is offline.
If no errors occur, the view returns a JSONResponse with a 200 “Success” status and a data object. If a KeyError occurs, the view will return a 500 “Internal Server Error” status. A KeyError occurs when the requested key of an object doesn’t exist.
In the next step, we’ll create corresponding URL routes to match the views we’ve created.
Step 3 — Mapping URLs to Views
Django makes it possible to create URLs that connect to views with a Python module called a URLconf. This module maps URL path expressions to Python functions (your views). Usually, a URL configuration file is auto-generated when you create a project. In this step, you will update this file to include new routes for the views you created in the previous step, along with the URLs for the django-webpush app, which will provide endpoints to subscribe users to push notifications.
For more information about views, please see How To Create Django Views.
Open urls.py:
nano ~/djangopush/djangopush/urls.py
The file will look like this:
~/djangopush/djangopush/urls.py
“””untitled URL Configuration
The urlpatterns
list routes URLs to views. For more information please see:
https://docs.djangoproject.com/en/2.1/topics/http/urls/
Examples:
Function views
1. Add an import: from my_app import views
2. Add a URL to urlpatterns: path(”, views.home, name=’home’)
Class-based views
1. Add an import: from other_app.views import Home
2. Add a URL to urlpatterns: path(”, Home.as_view(), name=’home’)
Including another URLconf
1. Import the include() function: from django.urls import include, path
2. Add a URL to urlpatterns: path(‘blog/’, include(‘blog.urls’))
“””
from django.contrib import admin
from django.urls import path
urlpatterns = [
path(‘admin/’, admin.site.urls),
]
The next step is to map the views you’ve created to URLs. First, add the include import to ensure that all of the routes for the Django-Webpush library will be added to your project:
~/djangopush/djangopush/urls.py
“””webpushdjango URL Configuration
…
“””
from django.contrib import admin
from django.urls import path, include
Next, import the views you created in the last step and update the urlpatterns list to map your views:
~/djangopush/djangopush/urls.py
“””webpushdjango URL Configuration
…
“””
from django.contrib import admin
from django.urls import path, include
from .views import home, send_push
urlpatterns = [
path(‘admin/’, admin.site.urls),
path(”, home),
path(‘send_push’, send_push),
path(‘webpush/’, include(‘webpush.urls’)),
]
Here, the urlpatterns list registers the URLs for the django-webpush package and maps your views to the URLs /send_push and /home.
Let’s test the /home view to be sure that it’s working as intended. Make sure you’re in the root directory of the project:
cd ~/djangopush
Start your server by running the following command:
python manage.py runserver your_server_ip:8000
Naviguez jusqu’à http://your_server_ip:8000. Vous devriez voir la page d’accueil suivante :
Initial Home Page view
À ce stade, vous pouvez tuer le serveur avec CTRL+C, et nous passons à la création de modèles et rendant dans nos points de vue à l’aide de la fonction de render .
Étape 4-Création de modèles
Moteur de template de Django vous permet de définir les couches face à l’utilisateur de votre application avec des gabarits, qui sont similaires aux fichiers HTML. Dans cette étape, vous créerez et restitue un modèle pour la vue home .
Créez un dossier nommé templates dans le répertoire racine de votre projet :
mkdir ~/djangopush/templates
Si vous exécutez ls dans le dossier racine de votre projet à ce stade, la sortie ressemblera à ceci :
Output
/djangopush
/templates
db.sqlite3
manage.py
/my_env
Créez un fichier appelé home.html dans le dossier templates :
nano ~/djangopush/templates/home.html
Ajoutez le code suivant au fichier pour créer un formulaire où les utilisateurs peuvent entrer des informations pour créer des notifications push :
{% load static %}
{% if user.id %}
{% endif %}
Le body du fichier inclut un formulaire contenant deux champs : un élément input tiendra la tête/titre de la notification, et un élément textarea tiendra le corps de la notification.
Dans la section head du fichier, il existe deux balises meta qui contiendra la clé publique insipide et l’id de l’utilisateur. Ces deux variables sont tenus d’inscrire un utilisateur et envoyer les avis de Poussée. Id de l’utilisateur est requis ici parce que vous allez envoyer requêtes AJAX sur le serveur et l’ id sera utilisé pour identifier l’utilisateur. Si l’utilisateur actuel est un usager inscrit, puis le modèle créera une balise meta avec leur id comme contenu.
L’étape suivante consiste à dire Django où trouver vos modèles. Pour ce faire, vous modifiez settings.py et mettre à jour la liste des TEMPLATES .
Ouvrez le fichier settings.py :
nano ~/djangopush/djangopush/settings.py
Ajouter ce qui suit à la liste de DIRS pour spécifier le chemin vers le répertoire templates :
~/djangopush/djangopush/Settings.py
…
TEMPLATES = [
{
‘BACKEND’: ‘django.template.backends.django.DjangoTemplates’,
‘DIRS’: [os.path.join(BASE_DIR, ‘templates’)],
‘APP_DIRS’: True,
‘OPTIONS’: {
‘context_processors’: [
…
],
},
},
]
…
Ensuite, dans votre fichier views.py , actualiser l’affichage home afin d’afficher le modèle home.html . Ouvrir le fichier :
nano ~/djangpush/djangopush/views.py
Tout d’abord, ajoutez quelques importations supplémentaires, y compris la configuration de settings , qui contient tous les paramètres du projet dans le fichier settings.py et la fonction de render de django.shortcuts:
~/djangopush/djangopush/views.py
…
from django.shortcuts import render, get_object_or_404
…
import json
from django.conf import settings
…
Ensuite, supprimer le code initial, que vous avez ajouté à la vue de home et ajoutez le code suivant, qui indique comment le modèle que vous venez de créer sera rendu :
~/djangopush/djangopush/views.py
…
@require_GET
def home(request):
webpush_settings = getattr(settings, ‘WEBPUSH_SETTINGS’, {})
vapid_key = webpush_settings.get(‘VAPID_PUBLIC_KEY’)
user = request.user
return render(request, ‘home.html’, {user: user, ‘vapid_key’: vapid_key})
Le code assigne les variables suivantes :
webpush_settings: c’est affecté de la valeur de l’attribut WEBPUSH_SETTINGS de la configuration de settings .
vapid_key: il obtient la valeur VAPID_PUBLIC_KEY de l’objet webpush_settings à envoyer au client. Cette clé publique est comparée à la clé privée pour s’assurer que le client avec la clé publique est autorisé à recevoir les messages push depuis le serveur.
user: cette variable provient de la requête entrante. Chaque fois qu’un utilisateur fait une demande au serveur, les détails de cet utilisateur sont stockés dans le domaine de user .
La fonction render retourne un fichier HTML et un objet de contexte contenant l’utilisateur actuel et la clé publique insipide du serveur. Elle accepte trois paramètres ici : la request, le template à afficher et l’objet qui contient les variables qui seront utilisés dans le modèle.
Avec notre modèle créé et la vue home mis à jour, nous pouvons passer à la configuration de Django pour desservir nos fichiers statiques.
Étape 5 — Servir des fichiers statiques
Applications Web incluent des CSS, JavaScript et autres fichiers d’image que Django qualifie de « fichiers statiques ». Django permet de collecter tous les fichiers statiques de chaque application de votre projet en un seul endroit d’où ils sont servis. Cette solution s’appelle django.contrib.staticfiles. Dans cette étape, nous mettrons à jour nos réglages pour dire Django où seront stockés les fichiers statiques.
Ouvrir settings.py:
nano ~/djangopush/djangopush/settings.py
Dans settings.py, tout d’abord s’assurer que le STATIC_URL a été défini :
~/djangopush/djangopush/Settings.py
…
STATIC_URL = ‘/static/’
Ajoutez ensuite une liste de répertoires appelés STATICFILES_DIRS où Django recherchera les fichiers statiques :
~/djangopush/djangopush/Settings.py
…
STATIC_URL = ‘/static/’
STATICFILES_DIRS = [
os.path.join(BASE_DIR, “static”),
]
Vous pouvez maintenant ajouter le STATIC_URL à la liste des chemins d’accès définis dans votre fichier urls.py .
Ouvrir le fichier :
nano ~/djangopush/djangopush/urls.py
Ajoutez le code suivant, qui va importer la configuration d’url static et mettre à jour la liste de urlpatterns . La fonction d’assistance ici utilise les propriétés STATIC_URL et STATIC_ROOT , que nous avons fourni dans le fichier settings.py pour servir des fichiers statiques du projet :
~/djangopush/djangopush/URLs.py
…
from django.conf import settings
from django.conf.urls.static import static
urlpatterns = [
…
] + static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
Avec notre statique fichiers paramètres configurés, nous pouvons passer à coiffer la page d’accueil de l’application.
Étape 6-Style de la Page d’accueil
Après avoir configuré votre application pour servir des fichiers statiques, vous pouvez créer une feuille de style externe et le lien vers le fichier home.html au style de la page d’accueil. Tous vos fichiers statiques sont sauvegardées dans un répertoire static dans le dossier racine de votre projet.
Créez un dossier static et un dossier css dans le dossier static :
mkdir -p ~/djangopush/static/css
Ouvrez un fichier css nommé styles.css dans le dossier css :
nano ~/djangopush/static/css/styles.css
Ajouter les styles suivants pour la page d’accueil :
~/djangopush/static/css/styles.CSS
body {
height: 100%;
background: rgba(0, 0, 0, 0.87);
font-family: ‘PT Sans’, sans-serif;
}
div {
height: 100%;
display: flex;
align-items: center;
justify-content: center;
}
form {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
width: 35%;
margin: 10% auto;
}
form > h3 {
font-size: 17px;
font-weight: bold;
margin: 15px 0;
color: orangered;
text-transform: uppercase;
}
form > .error {
margin: 0;
font-size: 15px;
font-weight: normal;
color: orange;
opacity: 0.7;
}
form > input, form > textarea {
border: 3px solid orangered;
box-shadow: unset;
padding: 13px 12px;
margin: 12px auto;
width: 80%;
font-size: 13px;
font-weight: 500;
}
form > input:focus, form > textarea:focus {
border: 3px solid orangered;
box-shadow: 0 2px 3px 0 rgba(0, 0, 0, 0.2);
outline: unset;
}
form > button {
justify-self: center;
padding: 12px 25px;
border-radius: 0;
text-transform: uppercase;
font-weight: 600;
background: orangered;
color: white;
border: none;
font-size: 14px;
letter-spacing: -0.1px;
cursor: pointer;
}
form > button:disabled {
background: dimgrey;
cursor: not-allowed;
}
Avec la feuille de style créée, vous pouvez le lier au fichier home.html à l’aide de balises de modèle statique. Ouvrez le fichier home.html :
nano ~/djangopush/templates/home.html
Mise à jour de la section de head afin d’inclure un lien vers la feuille de style externe :
~/djangopush/templates/Home.html
{% load static %}
…
…
Assurez-vous que vous êtes dans votre répertoire de projet principal et démarrez votre serveur à nouveau pour inspecter votre travail :
cd ~/djangopush
python manage.py runserver your_server_ip:8000
Lorsque vous visitez http://your_server_ip:8000, il devrait ressembler à ceci :
Home page view
Encore une fois, vous pouvez tuer le serveur avec CTRL+C.
Maintenant que vous avez créé la page home.html et ce style, vous pouvez vous abonner aux utilisateurs pour exécuter un push notifications chaque fois qu’ils visitent la page d’accueil.
Étape 7-Enregistrant un travailleur des services et s’abonner aux utilisateurs pour exécuter un Push Notifications
Notifications push Web peuvent avertir les utilisateurs lorsqu’il sont mises à jour d’ils sont abonnés à des applications ou les inciter à reprendre avec les applications qu’ils utilisent dans le passé. Ils s’appuient sur deux technologies, le push API et les notifications API. Les deux technologies reposent sur la présence d’un travailleur de service.
Un coup de pouce est appelé lorsque le serveur fournit des informations à l’ouvrier de service et l’ouvrier de service utilise les notifications API pour afficher ces informations.
Nous vais vous abonner à nos utilisateurs des pousser et puis nous vous enverrons les informations de l’abonnement au serveur de les enregistrer.
Dans le répertoire static , créez un dossier appelé js:
mkdir ~/djangopush/static/js
Créez un fichier appelé registerSw.js:
nano ~/djangopush/static/js/registerSw.js
Ajoutez le code suivant, qui vérifie si les travailleurs des services sont pris en charge sur le navigateur de l’utilisateur avant d’enregistrer un travailleur des services :
~/djangopush/static/js/registerSw.js
const registerSw = async () => {
if (‘serviceWorker’ in navigator) {
const reg = await navigator.serviceWorker.register(‘sw.js’);
initialiseState(reg)
} else {
showNotAllowed(“You can’t send push notifications ☹️😢”)
}
};
Tout d’abord, la fonction registerSw vérifie si le navigateur prend en charge les travailleurs des services avant leur inscription. Après l’inscription, il appelle la fonction de initializeState avec les données d’inscription. Si les techniciens ne sont pas supportés dans le navigateur, il appelle la fonction showNotAllowed .
Ensuite, ajoutez le code suivant sous la fonction registerSw pour vérifier si un utilisateur est admissible à recevoir des notifications de type pousser avant de tenter de s’abonner à eux :
~/djangopush/static/js/registerSw.js
…
const initialiseState = (reg) => {
if (!reg.showNotification) {
showNotAllowed(‘Showing notifications isn\’t supported ☹️😢’);
return
}
if (Notification.permission === ‘denied’) {
showNotAllowed(‘You prevented us from showing notifications ☹️🤔’);
return
}
if (!’PushManager’ in window) {
showNotAllowed(“Push isn’t allowed in your browser 🤔”);
return
}
subscribe(reg);
}
const showNotAllowed = (message) => {
const button = document.querySelector(‘form>button’);
button.innerHTML = ${message}
;
button.setAttribute(‘disabled’, ‘true’);
};
La fonction initializeState vérifie ce qui suit :
Si l’utilisateur a activé des notifications, à l’aide de la valeur de reg.showNotification.
Si l’utilisateur a l’autorisation application pour afficher les notifications.
Si le navigateur prend en charge le PushManager API. Si une de ces vérifications échoue, la fonction showNotAllowed est appelée et l’abonnement est abandonnée.
La fonction showNotAllowed affiche un message sur le bouton et il désactive si un utilisateur n’est pas admissible à recevoir des notifications. Il affiche également les messages appropriés si un utilisateur a restreint l’application de l’affichage des notifications ou si le navigateur ne supporte pas les notifications push.
Une fois que nous assurer qu’un utilisateur est admissible à recevoir des notifications push, l’étape suivante consiste à s’abonner à l’aide de pushManager. Ajoutez le code suivant sous la fonction showNotAllowed :
~/djangopush/static/js/registerSw.js
…
function urlB64ToUint8Array(base64String) {
const padding = ‘=’.repeat((4 – base64String.length % 4) % 4);
const base64 = (base64String + padding)
.replace(/\-/g, ‘+’)
.replace(/_/g, ‘/’);
const rawData = window.atob(base64);
const outputArray = new Uint8Array(rawData.length);
const outputData = outputArray.map((output, index) => rawData.charCodeAt(index));
return outputData;
}
const subscribe = async (reg) => {
const subscription = await reg.pushManager.getSubscription();
if (subscription) {
sendSubData(subscription);
return;
}
const vapidMeta = document.querySelector(‘meta[name=”vapid-key”]’);
const key = vapidMeta.content;
const options = {
userVisibleOnly: true,
// if key exists, create applicationServerKey property
…(key && {applicationServerKey: urlB64ToUint8Array(key)})
};
const sub = await reg.pushManager.subscribe(options);
sendSubData(sub)
};
Appeler la fonction pushManager.getSubscription retourne les données pour un abonnement actif. Lorsqu’il existe un abonnement actif, la fonction sendSubData est appelée avec l’abonnement info passé comme un paramètre.
Lorsque aucun abonnement actif n’existe, la clé publique insipide, qui est Base64 sécurisé URL codée, est converti en une Uint8Array à l’aide de la fonction urlB64ToUint8Array . pushManager.subscribe est ensuite appelée avec la clé publique insipide et la valeur de userVisible en option. Vous pouvez en savoir plus sur les options disponibles ici.
Après avoir avec succès souscrit un utilisateur, l’étape suivante consiste à envoyer les données d’abonnement sur le serveur. Les données seront envoyées au point de terminaison webpush/save_information fourni par le paquet de django-webpush . Ajoutez le code suivant sous la fonction subscribe :
~/djangopush/static/js/registerSw.js
…
const sendSubData = async (subscription) => {
const browser = navigator.userAgent.match(/(firefox|msie|chrome|safari|trident)/ig)[0].toLowerCase();
const data = {
status_type: ‘subscribe’,
subscription: subscription.toJSON(),
browser: browser,
};
const res = await fetch(‘/webpush/save_information’, {
method: ‘POST’,
body: JSON.stringify(data),
headers: {
‘content-type’: ‘application/json’
},
credentials: “include”
});
handleResponse(res);
};
const handleResponse = (res) => {
console.log(res.status);
};
registerSw();
Le point de terminaison save_information requiert des informations sur l’état de l’abonnement (subscribe et unsubscribe), les données d’abonnement et le navigateur. Enfin, nous appelons la fonction registerSw() pour lancer le processus d’abonnement de l’utilisateur.
Le fichier ressemble à ceci :
~/djangopush/static/js/registerSw.js
const registerSw = async () => {
if (‘serviceWorker’ in navigator) {
const reg = await navigator.serviceWorker.register(‘sw.js’);
initialiseState(reg)
} else {
showNotAllowed(“You can’t send push notifications ☹️😢”)
}
};
const initialiseState = (reg) => {
if (!reg.showNotification) {
showNotAllowed(‘Showing notifications isn\’t supported ☹️😢’);
return
}
if (Notification.permission === ‘denied’) {
showNotAllowed(‘You prevented us from showing notifications ☹️🤔’);
return
}
if (!’PushManager’ in window) {
showNotAllowed(“Push isn’t allowed in your browser 🤔”);
return
}
subscribe(reg);
}
const showNotAllowed = (message) => {
const button = document.querySelector(‘form>button’);
button.innerHTML = ${message}
;
button.setAttribute(‘disabled’, ‘true’);
};
function urlB64ToUint8Array(base64String) {
const padding = ‘=’.repeat((4 – base64String.length % 4) % 4);
const base64 = (base64String + padding)
.replace(/\-/g, ‘+’)
.replace(/_/g, ‘/’);
const rawData = window.atob(base64);
const outputArray = new Uint8Array(rawData.length);
const outputData = outputArray.map((output, index) => rawData.charCodeAt(index));
return outputData;
}
const subscribe = async (reg) => {
const subscription = await reg.pushManager.getSubscription();
if (subscription) {
sendSubData(subscription);
return;
}
const vapidMeta = document.querySelector(‘meta[name=”vapid-key”]’);
const key = vapidMeta.content;
const options = {
userVisibleOnly: true,
// if key exists, create applicationServerKey property
…(key && {applicationServerKey: urlB64ToUint8Array(key)})
};
const sub = await reg.pushManager.subscribe(options);
sendSubData(sub)
};
const sendSubData = async (subscription) => {
const browser = navigator.userAgent.match(/(firefox|msie|chrome|safari|trident)/ig)[0].toLowerCase();
const data = {
status_type: ‘subscribe’,
subscription: subscription.toJSON(),
browser: browser,
};
const res = await fetch(‘/webpush/save_information’, {
method: ‘POST’,
body: JSON.stringify(data),
headers: {
‘content-type’: ‘application/json’
},
credentials: “include”
});
handleResponse(res);
};
const handleResponse = (res) => {
console.log(res.status);
};
registerSw();
Ensuite, ajoutez une balise de script du fichier registerSw.js dans home.html. Ouvrir le fichier :
nano ~/djangopush/templates/home.html
Ajoutez la balise de script avant la balise fermante de l’élément body :
~/djangopush/templates/Home.html
{% load static %}
…
…
Parce qu’un travailleur de service n’existe pas encore, si vous laissé votre application en cours d’exécution ou essayé de le démarrer à nouveau, vous verrez un message d’erreur. Nous allons résoudre ce problème en créant un travailleur des services.
Étape 8 — Création d’un travailleur des services
Pour afficher une notification push, vous aurez besoin d’un travailleur de service actif installé sur la page d’accueil de votre application. Nous allons créer un ouvrier de service qui écoute les événements de push et affiche les messages lorsque vous êtes prêt.
Parce que nous voulons que la portée de l’ouvrier de service à l’ensemble du domaine, nous aurons besoin de l’installer dans la racine de l’application. Vous pouvez en savoir plus sur le processus dans cet article expliquant Comment enregistrer un travailleur des services. Notre approche consistera à créer un fichier sw.js dans le dossier templates , qui nous enregistrerons alors comme un point de vue.
Créez le fichier :
nano ~/djangopush/templates/sw.js
Ajoutez le code suivant, qui raconte le travailleur des services à l’écoute des événements de push :
~/djangopush/templates/SW.js
// Register event listener for the ‘push’ event.
self.addEventListener(‘push’, function (event) {
// Retrieve the textual payload from event.data (a PushMessageData object).
// Other formats are supported (ArrayBuffer, Blob, JSON), check out the documentation
// on https://developer.mozilla.org/en-US/docs/Web/API/PushMessageData.
const eventInfo = event.data.text();
const data = JSON.parse(eventInfo);
const head = data.head || ‘New Notification 🕺🕺’;
const body = data.body || ‘This is default content. Your notification didn\’t have one 🙄🙄’;
// Keep the service worker alive until the notification is created.
event.waitUntil(
self.registration.showNotification(head, {
body: body,
icon: ‘https://i.imgur.com/MZM3K5w.png’
})
);
});
Les travailleurs du service écoute un événement de pousser. Dans la fonction de rappel, les données event sont converties en texte. Nous utilisons des chaînes de title et le body par défaut si les données d’événement ne les ont pas. La fonction showNotification prend le titre de notification, l’en-tête de la notification s’affiche et un objet d’options comme paramètres. L’objet options contient plusieurs propriétés pour configurer les options visuelles d’une notification.
Pour votre travailleur des services à travailler pour l’intégralité de votre domaine, vous devrez l’installer à la racine de l’application. Nous allons utiliser TemplateView pour permettre l’accès de travailleurs de service à l’ensemble du domaine.
Ouvrez le fichier urls.py :
nano ~/djangopush/djangopush/urls.py
Ajoutez une nouvelle déclaration d’importation et le chemin d’accès dans la liste de urlpatterns pour créer un affichage basé sur la classe :
~/djangopush/djangopush/URLs.py
…
from django.views.generic import TemplateView
urlpatterns = [
…,
path(‘sw.js’, TemplateView.as_view(template_name=’sw.js’, content_type=’application/x-javascript’))
] + static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
Basés sur une classe vues comme TemplateView vous permettent de créer des affichages flexibles et réutilisables. Dans ce cas, la méthode TemplateView.as_view crée un chemin pour le travailleur de service en passant le travailleur service récemment créée en tant que modèle et application/x-javascript comme le content_type du modèle.
Vous avez maintenant créé un ouvrier de service et il inscrit comme un itinéraire. Ensuite, vous définirez le formulaire sur la page d’accueil d’envoyer des notifications push.
Étape 9 — Envoi de Notifications Push
En utilisant le formulaire sur la page d’accueil, les utilisateurs doivent être en mesure d’envoyer des notifications de type pousser alors que votre serveur est en cours d’exécution. Vous pouvez également envoyer des notifications de type pousser à l’aide de n’importe quel service RESTful comme postier. Lorsque l’utilisateur envoie des notifications de type pousser du formulaire sur la page d’accueil, les données comprendront une head et body, ainsi que l’ id de l’utilisateur destinataire. Les données doivent être structurées de la manière suivante :
{
head: “Title of the notification”,
body: “Notification body”,
id: “User’s id”
}
Pour écouter l’événement submit le formulaire et envoyer les données entrées par l’utilisateur sur le serveur, nous allons créer un fichier appelé site.js dans le répertoire ~/djangopush/static/js .
Ouvrir le fichier :
nano ~/djangopush/static/js/site.js
Tout d’abord, ajoutez un écouteur d’événements submit au formulaire qui vous permettra d’obtenir les valeurs des entrées de la forme et l’id de l’utilisateur stockées dans la balise meta de votre modèle :
~/djangopush/static/js/site.js
const pushForm = document.getElementById(‘send-push__form’);
const errorMsg = document.querySelector(‘.error’);
pushForm.addEventListener(‘submit’, async function (e) {
e.preventDefault();
const input = this[0];
const textarea = this[1];
const button = this[2];
errorMsg.innerText = ”;
const head = input.value;
const body = textarea.value;
const meta = document.querySelector(‘meta[name=”user_id”]’);
const id = meta ? meta.content : null;
…
// TODO: make an AJAX request to send notification
});
La fonction pushForm obtient input, textareaet button à l’intérieur de la forme. Il obtient également les informations de la balise meta , y compris le nom attribut user_id et l’id de l’utilisateur stockée dans l’attribut content de la balise. Avec cette information, il peut envoyer une requête POST vers le point de terminaison /send_push sur le serveur.
Pour envoyer des requêtes vers le serveur, nous allons utiliser le natif Fetch API. Nous utilisons Fetch ici parce qu’il est pris en charge par la plupart des navigateurs et ne requiert pas de bibliothèques externes pour fonctionner. Ci-dessous le code que vous avez ajoutée, mise à jour de la fonction pushForm pour inclure le code pour l’envoi de requêtes AJAX :
~/djangopush/static/js/site.js
const pushForm = document.getElementById(‘send-push__form’);
const errorMsg = document.querySelector(‘.error’);
pushForm.addEventListener(‘submit’, async function (e) {
…
const id = meta ? meta.content : null;
if (head && body && id) {
button.innerText = ‘Sending…’;
button.disabled = true;
const res = await fetch(‘/send_push’, {
method: ‘POST’,
body: JSON.stringify({head, body, id}),
headers: {
‘content-type’: ‘application/json’
}
});
if (res.status === 200) {
button.innerText = ‘Send another 😃!’;
button.disabled = false;
input.value = ”;
textarea.value = ”;
} else {
errorMsg.innerText = res.message;
button.innerText = ‘Something broke 😢.. Try again?’;
button.disabled = false;
}
}
else {
let error;
if (!head || !body){
error = ‘Please ensure you complete the form 🙏🏾’
}
else if (!id){
error = “Are you sure you’re logged in? 🤔. Make sure! 👍🏼”
}
errorMsg.innerText = error;
}
});
Si besoin est les trois paramètres, head, bodyet id sont présents, nous envoyer la demande et désactiver le bouton Soumettre temporairement.
Le fichier ressemble à ceci :
~/djangopush/static/js/site.js
const pushForm = document.getElementById(‘send-push__form’);
const errorMsg = document.querySelector(‘.error’);
pushForm.addEventListener(‘submit’, async function (e) {
e.preventDefault();
const input = this[0];
const textarea = this[1];
const button = this[2];
errorMsg.innerText = ”;
const head = input.value;
const body = textarea.value;
const meta = document.querySelector(‘meta[name=”user_id”]’);
const id = meta ? meta.content : null;
if (head && body && id) {
button.innerText = ‘Sending…’;
button.disabled = true;
const res = await fetch(‘/send_push’, {
method: ‘POST’,
body: JSON.stringify({head, body, id}),
headers: {
‘content-type’: ‘application/json’
}
});
if (res.status === 200) {
button.innerText = ‘Send another 😃!’;
button.disabled = false;
input.value = ”;
textarea.value = ”;
} else {
errorMsg.innerText = res.message;
button.innerText = ‘Something broke 😢.. Try again?’;
button.disabled = false;
}
}
else {
let error;
if (!head || !body){
error = ‘Please ensure you complete the form 🙏🏾’
}
else if (!id){
error = “Are you sure you’re logged in? 🤔. Make sure! 👍🏼”
}
errorMsg.innerText = error;
}
});
Enfin, ajoutez le fichier site.js dans home.html:
nano ~/djangopush/templates/home.html
Ajoutez la balise script :
~/djangopush/templates/Home.html
{% load static %}
…
…
À ce stade, si vous laissé votre application en cours d’exécution ou essayé de le démarrer à nouveau, vous verriez une erreur, étant donné que les travailleurs des services ne peuvent fonctionner que dans des domaines sécurisés ou sur localhost. Dans l’étape suivante, nous allons utiliser ngrok pour créer un tunnel sécurisé sur notre serveur web.
Étape 10 — Création d’un Tunnel sécurisé pour tester l’Application
Travailleurs des services exigent des connexions sécurisées pour fonctionner sur n’importe quel site sauf localhost puisqu’ils peuvent autoriser les connexions à être détourné et réponses à être filtrée et fabriqué. Pour cette raison, nous allons créer un tunnel sécurisé pour notre serveur avec ngrok.
Ouvrir une deuxième fenêtre de terminal et de s’assurer que vous êtes dans votre répertoire home :
cd ~
Si vous avez commencé avec un serveur propre 18.04 dans la configuration requise, vous devrez ensuite installer unzip:
sudo apt update && sudo apt install unzip
Télécharger ngrok :
wget https://bin.equinox.io/c/4VmDzA7iaHb/ngrok-stable-linux-amd64.zip
unzip ngrok-stable-linux-amd64.zip
Déplacez ngrok vers /usr/local/bin, afin que vous aurez accès à la commande de ngrok depuis le terminal :
sudo mv ngrok /usr/local/bin
Dans votre première fenêtre de terminal, vérifiez que vous êtes dans le répertoire de votre projet et démarrez votre serveur :
cd ~/djangopush
python manage.py runserver your_server_ip:8000
Vous devrez le faire avant de créer un tunnel sécurisé pour votre application.
Dans votre deuxième fenêtre de terminal, naviguez jusqu’à votre dossier de projet et activer votre environnement virtuel :
cd ~/djangopush
source my_env/bin/activate
Créer le tunnel sécurisé à votre application :
ngrok http your_server_ip:8000
Vous verrez la sortie suivante, qui comporte des informations sur l’URL de votre ngrok sûr :
Output
ngrok 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
Copier le ngrok_secure_url de la sortie de la console. Vous devrez l’ajouter à la liste ALLOWED_HOSTS dans votre fichier settings.py .
Ouvrez une autre fenêtre de terminal, naviguez jusqu’à votre dossier de projet et activer votre environnement virtuel :
cd ~/djangopush
source my_env/bin/activate
Ouvrez le fichier settings.py :
nano ~/djangopush/djangopush/settings.py
Mettre à jour la liste des ALLOWED_HOSTS avec le tunnel sécurisé de ngrok :
~/djangopush/djangopush/Settings.py
…
ALLOWED_HOSTS = [‘your_server_ip’, ‘ngrok_secure_url’]
…
Accédez à la page d’admin sécurisé pour vous connecter : https://ngrok_secure_url/admin/. Vous verrez un écran qui ressemble à ceci :
ngrok admin login
Entrez vos informations d’utilisateur admin Django sur cet écran. Cela devrait être la même information que vous avez entré lorsque vous vous êtes connecté à l’interface d’admin dans les étapes préalables. Vous êtes maintenant prêt à envoyer des notifications push.
Visitez https://ngrok_secure_url dans votre navigateur. Vous verrez une invite demandant l’autorisation d’afficher les notifications. Cliquez sur le bouton autoriser pour laisser votre navigateur à afficher les notifications push :
push notifications request
Soumettre un formulaire rempli affichera une notification semblable à ceci :
screenshot of notification
Remarque : N’oubliez pas que votre serveur est en cours d’exécution avant d’essayer d’envoyer des notifications.
Si vous avez reçu des notifications puis votre application fonctionne comme prévu.
Vous avez créé une application web qui déclenche des notifications push sur le serveur et, avec l’aide de techniciens, reçoit et affiche des notifications. Vous êtes aussi allé à travers les étapes d’obtenir les clés INSIPIDES qui sont tenus d’envoyer des notifications push depuis un serveur d’applications.
Conclusion
Dans ce didacticiel, vous avez appris comment s’abonner aux utilisateurs pour repousser les notifications, installer des ouvriers de service et afficher les notifications de transmission utilisant les notifications API.
Vous pouvez aller encore plus loin en configurant les notifications pour ouvrir les zones spécifiques de votre application lorsque vous cliquez dessus. Le code source de ce didacticiel se trouvent ici.