Présentation
Les bibliothèques clientes Cloud sont la méthode recommandée pour appeler les API Google Cloud à partir de vos applications. Elles utilisent les conventions et le style naturels du langage de programmation dont vous vous servez pour votre application. Les bibliothèques clientes Cloud gèrent la communication de bas niveau avec le serveur, y compris l'authentification et la logique de nouvelle tentative.
Conçu pour le scaling automatique et les hautes performances, Firestore est une base de données de documents NoSQL sans serveur, entièrement gérée et rapide qui simplifie le développement d'applications.
Les API Google utilisent le protocole OAuth 2.0 pour l'authentification et l'autorisation.
Secret Manager vous permet de stocker des clés API, des mots de passe, des certificats et d'autres données sensibles sous forme de blobs binaires ou de chaînes de texte.
L'API Cloud Translation permet à vos sites Web et à vos applications de traduire dynamiquement du texte de manière programmatique. Cloud Translation peut traduire du texte dans plus de 100 langues et détecter la langue du texte source.
Dans cet atelier, vous allez mettre à jour une application Python qui gère une liste de livres. Vous allez ajouter la possibilité de se connecter à l'application à l'aide d'OAuth et d'exiger que l'utilisateur se connecte pour ajouter, modifier ou supprimer des livres.
Vous allez également utiliser l'API Cloud Translation pour traduire les descriptions des livres dans une autre langue. Vous allez ajouter un profil utilisateur qui stocke la langue préférée de l'utilisateur.
Objectifs de l'atelier
Dans cet atelier, vous apprendrez à effectuer les tâches suivantes :
- Créer une application Web Python Flask simple
- Utiliser Secret Manager pour stocker les données d'application sensibles
- Utiliser OAuth 2.0 pour ajouter la connexion utilisateur à une application
- Utiliser l'API Cloud Translation pour détecter la langue du texte et le traduire
Préparation
Avant de cliquer sur le bouton "Démarrer l'atelier"
Remarque : Lisez ces instructions.
Les ateliers sont minutés, et vous ne pouvez pas les mettre en pause. Le minuteur, qui démarre lorsque vous cliquez sur Démarrer l'atelier, indique combien de temps les ressources Google Cloud resteront accessibles.
Cet atelier pratique Qwiklabs vous permet de suivre vous-même les activités dans un véritable environnement cloud, et non dans un environnement de simulation ou de démonstration. Des identifiants temporaires vous sont fournis pour vous permettre de vous connecter à Google Cloud le temps de l'atelier.
Conditions requises
Pour réaliser cet atelier, vous devez :
- avoir accès à un navigateur Internet standard (nous vous recommandons d'utiliser Chrome) ;
- disposer de suffisamment de temps pour effectuer l'atelier en une fois.
Remarque : Si vous possédez déjà votre propre compte ou projet Google Cloud, veillez à ne pas l'utiliser pour réaliser cet atelier.
Remarque : Si vous utilisez un Pixelbook, veuillez exécuter cet atelier dans une fenêtre de navigation privée.
Démarrer votre atelier et vous connecter à la console
-
Cliquez sur le bouton Démarrer l'atelier. Si l'atelier est payant, un pop-up s'affiche pour vous permettre de sélectionner un mode de paiement.
Sur la gauche, vous verrez un panneau contenant les identifiants temporaires à utiliser pour cet atelier.

-
Copiez le nom d'utilisateur, puis cliquez sur Ouvrir la console Google.
L'atelier lance les ressources, puis la page Sélectionner un compte dans un nouvel onglet.
Remarque : Ouvrez les onglets dans des fenêtres distinctes, placées côte à côte.
-
Sur la page "Sélectionner un compte", cliquez sur Utiliser un autre compte. La page de connexion s'affiche.

-
Collez le nom d'utilisateur que vous avez copié dans le panneau "Détails de connexion". Copiez et collez ensuite le mot de passe.
Remarque : Vous devez utiliser les identifiants fournis dans le panneau "Détails de connexion", et non vos identifiants Google Cloud Skills Boost. Si vous possédez un compte Google Cloud, ne vous en servez pas pour cet atelier (vous éviterez ainsi que des frais vous soient facturés).
- Accédez aux pages suivantes :
- Acceptez les conditions d'utilisation.
- N'ajoutez pas d'options de récupération ni d'authentification à deux facteurs (ce compte est temporaire).
- Ne vous inscrivez pas aux essais offerts.
Après quelques instants, la console Cloud s'ouvre dans cet onglet.
Remarque : Vous pouvez afficher le menu qui contient la liste des produits et services Google Cloud en cliquant sur le menu de navigation en haut à gauche.
Activer Google Cloud Shell
Google Cloud Shell est une machine virtuelle qui contient de nombreux outils pour les développeurs. Elle comprend un répertoire d'accueil persistant de 5 Go et s'exécute sur Google Cloud.
Google Cloud Shell vous permet d'accéder à vos ressources Google Cloud grâce à une ligne de commande.
-
Dans la barre d'outils située en haut à droite dans la console Cloud, cliquez sur le bouton "Ouvrir Cloud Shell".

-
Cliquez sur Continuer.
Le provisionnement et la connexion à l'environnement prennent quelques instants. Une fois connecté, vous êtes en principe authentifié et le projet est défini sur votre ID_PROJET. Par exemple :

gcloud est l'outil de ligne de commande pour Google Cloud. Il est préinstallé sur Cloud Shell et permet la complétion par tabulation.
- Vous pouvez lister les noms des comptes actifs à l'aide de cette commande :
gcloud auth list
Résultat :
Credentialed accounts:
- @.com (active)
Exemple de résultat :
Credentialed accounts:
- google1623327_student@qwiklabs.net
- Vous pouvez lister les ID de projet à l'aide de cette commande :
gcloud config list project
Résultat :
[core]
project =
Exemple de résultat :
[core]
project = qwiklabs-gcp-44776a13dea667a6
Remarque : Pour consulter la documentation complète sur gcloud, accédez au guide de présentation de la gcloud CLI.
Tâche 1 : Configurer l'application Python et les ressources nécessaires
Dans cette tâche, vous allez télécharger l'application Python et créer les ressources utilisées par la version actuelle de l'application.
Remarque : La plupart des langages utilisent le retrait pour rendre le code plus lisible. En Python, le retrait sert à indiquer un bloc de code. Il doit donc être correct. Le nombre d'espaces de retrait doit être cohérent. Utiliser à la fois des espaces et des tabulations comme indicateurs de retrait peut également entraîner des problèmes. Dans cet atelier, un retrait en Python correspond à une série de quatre espaces.
Créer la base de données Firestore
-
Pour créer la base de données Firestore, exécutez la commande suivante dans Cloud Shell :
gcloud firestore databases create --location={{{ project_0.default_region | region }}}
La base de données Firestore est utilisée pour stocker les données des livres et des profils utilisateur.
-
Si vous êtes invité à autoriser Cloud Shell, cliquez sur Autoriser.
Créer le bucket Cloud Storage avec les autorisations appropriées
-
Pour créer le bucket Cloud Storage, exécutez la commande suivante :
gcloud storage buckets create gs://{{{ project_0.project_id | project_id}}}-covers --location={{{ project_0.default_region | region }}} --no-public-access-prevention --uniform-bucket-level-access
Le bucket Cloud Storage est utilisé pour stocker les images des couvertures de livres. Il dispose d'un accès uniforme au niveau du bucket et n'utilise pas la protection contre l'accès public.
Remarque : Si la commande échoue avec un message d'erreur indiquant que les identifiants du compte ne sont pas valides, essayez de la réexécuter. Il se peut que les autorisations du compte participant Qwiklabs ne se soient pas encore propagées.
-
Pour rendre tous les objets du bucket lisibles publiquement, exécutez la commande suivante :
gcloud storage buckets add-iam-policy-binding gs://{{{ project_0.project_id | project_id}}}-covers --member=allUsers --role=roles/storage.legacyObjectReader
Cliquez sur Vérifier ma progression pour valider l'objectif.
Configurer l'application Python et les ressources nécessaires
Copier le code Python dans Cloud Shell
-
Pour copier le code Python d'un bucket Cloud Storage dans le répertoire d'accueil, exécutez la commande suivante :
gcloud storage cp gs://cloud-training/devapps-foundations/code/lab2/bookshelf.zip ~ && unzip ~/bookshelf.zip -d ~ && rm ~/bookshelf.zip
-
Pour vérifier le contenu du répertoire "bookshelf", exécutez la commande suivante :
cd ~
ls -R bookshelf
Vous devriez voir une liste contenant trois fichiers Python, un fichier d'exigences et quatre fichiers de modèle :
bookshelf:
booksdb.py main.py requirements.txt storage.py templates
bookshelf/templates:
base.html form.html list.html view.html
Installer les dépendances requises
-
Pour lister les dépendances dans le fichier d'exigences, exécutez la commande suivante :
cat ~/bookshelf/requirements.txt
Le fichier d'exigences spécifie les dépendances suivantes :
-
Flask : module de framework Web utilisé pour concevoir des applications Web Python
-
Gunicorn : serveur HTTP Python qui s'exécute sous Linux
-
Cloud Logging : produit qui permet de consigner les informations de l'application
-
Firestore : base de données de documents NoSQL sans serveur, entièrement gérée et rapide, conçue pour simplifier le développement d'applications
-
Cloud Storage : solution unifiée de stockage d'objets de Google Cloud
-
Pour installer les dépendances dans le fichier d'exigences, exécutez la commande suivante :
pip3 install -r ~/bookshelf/requirements.txt --user
pip est le programme d'installation de packages pour Python. La commande pip3
installe les packages spécifiés dans le fichier requirements.txt qui doivent être utilisés avec Python 3.
Tester l'application
-
Pour démarrer l'application, exécutez la commande suivante :
cd ~/bookshelf; ~/.local/bin/gunicorn -b :8080 main:app
Si vous avez réussi à créer les fichiers, l'application doit maintenant être hébergée sur le port 8080.
-
Pour exécuter l'application dans le navigateur Web, cliquez sur Aperçu sur le Web, puis sélectionnez Prévisualiser sur le port 8080.

Un nouvel onglet s'ouvre dans le navigateur et l'application s'exécute. Cette page affiche la liste de tous les livres existants. Aucun livre n'est disponible pour l'instant.
Remarque : Si un message vous demande d'autoriser Cloud Shell, cliquez sur Autoriser.
-
Effectuez un clic droit sur l'image de couverture du livre Le Magicien d'Oz, puis enregistrez-la sur votre ordinateur sous le nom oz.png
:

-
Dans l'onglet de l'application, cliquez sur + Ajouter un livre.
-
Saisissez les informations suivantes dans le formulaire :
Champ |
Valeur |
Titre |
Le Magicien d'Oz |
Auteur |
Frank L. Baum |
Date de publication |
1900 |
Description |
Une jeune fille et son chien sont transportés dans un pays magique, où ils rencontrent des gens étranges et découvrent qu'il vaut mieux ne pas se trouver sous une maison. |
-
Pour Image de couverture, cliquez sur Sélectionner un fichier.
-
Sélectionnez le fichier que vous avez téléchargé (oz.png), puis cliquez sur Ouvrir.
-
Cliquez sur Enregistrer.
Vous revenez à la page de vue, qui contient les détails du livre.
-
En haut de la page, cliquez sur Livres.
Vous êtes redirigé vers la page de liste, et Le Magicien d'Oz s'affiche dans la liste, avec sa couverture. Les détails du livre sont stockés dans la base de données Firestore et l'image de couverture est stockée dans Cloud Storage.
Remarque : Vous pouvez ajouter des livres, mais ne modifiez pas Le Magicien d'Oz. Vous allez l'utiliser pour le reste de l'atelier.
-
Dans Cloud Shell, pour quitter l'application, appuyez sur Ctrl+C
.
Cliquez sur Vérifier ma progression pour valider l'objectif.
Tester l'application et créer un livre
Tâche 2 : Créer des identifiants d'autorisation OAuth pour votre application
Dans cette tâche, vous allez créer des identifiants d'autorisation qui permettront à votre application d'être identifiée auprès du serveur OAuth 2.0 de Google.
Créer l'écran de consentement OAuth
Lorsque vous utilisez OAuth 2.0 pour gérer les autorisations, votre application demande des autorisations pour un ou plusieurs niveaux d'accès d'un compte Google. Google affiche un écran de consentement dans lequel l'utilisateur décide d'autoriser ou non le partage de ses données avec l'application.
-
Dans la console Google Cloud, accédez au menu de navigation (
), puis cliquez sur API et services > Écran de consentement OAuth.
Cette page vous permet de sélectionner le type d'utilisateurs de votre application. Les utilisateurs internes sont ceux qui appartiennent à votre organisation. Les utilisateurs externes sont tous ceux qui disposent d'un compte Google.
-
Cliquez sur Commencer.
-
Pour Nom de l'application, saisissez Bookshelf
.
-
Sous Adresse e-mail d'assistance utilisateur, sélectionnez l'adresse e-mail du participant.
-
Cliquez sur Suivant.
-
Sous Cible, sélectionnez Externe, puis cliquez sur Suivant.
Les utilisateurs disposant d'un compte de test pourront se connecter à l'application.
-
Dans le panneau de gauche des instructions de l'atelier, copiez le nom d'utilisateur.

-
Pour le champ Adresses e-mail, collez le nom d'utilisateur copié, puis cliquez sur Suivant.
-
Cochez la case pour accepter le règlement sur les données utilisateur, puis cliquez sur Continuer.
-
Cliquez sur Créer.
-
Dans le menu de navigation, cliquez sur Branding.
-
Cliquez sur + Ajouter un domaine.
-
Dans la section Domaines autorisés, saisissez cloudshell.dev
dans le champ Domaine autorisé 1.
Lorsque l'application s'exécute dans Cloud Shell, cloudshell.dev
est le nom de domaine.
-
Cliquez sur Enregistrer.
-
Dans le menu de navigation, cliquez sur Accès aux données.
Ensuite, vous devez sélectionner les niveaux d'accès demandés aux utilisateurs pour votre application. Les niveaux d'accès reflètent les types de données utilisateur privées du compte Google de l'utilisateur auxquels l'application souhaite accéder.
Il existe trois types de niveaux d'accès :
- Les niveaux d'accès sensibles, qui doivent être validés par Google avant de pouvoir être présentés à l'utilisateur dans un écran de consentement
- Les niveaux d'accès restreints, qui incluent des informations encore plus sensibles, provenant d'applications comme Gmail et Drive, et qui peuvent nécessiter un examen plus approfondi
- Les niveaux d'accès non sensibles, qui sont moins sensibles et ne nécessitent pas la validation de Google
-
Cliquez sur Ajouter ou supprimer des niveaux d'accès.
La liste des niveaux d'accès s'affiche.
-
Au début de la liste, cochez la case à côté de openid.
-
Pour Filtrer, saisissez userinfo.profile
, appuyez sur Entrée, puis cochez la case du niveau d'accès .../auth/userinfo.profile
.
-
Pour Filtrer, désactivez le filtre userinfo.profile, saisissez contacts
, appuyez sur Entrée, puis cochez la case du niveau d'accès .../auth/contacts
.
-
Cliquez sur Mettre à jour.
Vous devriez voir deux niveaux d'application non sensibles ("openid" et "userinfo.profile") et un niveau d'accès sensible ("contacts").
Remarque : Dans cet atelier, nous n'utiliserons pas le niveau d'accès "contacts", mais nous nous en servons ici comme exemple. Vos applications doivent utiliser les niveaux d'accès minimaux requis.
-
Cliquez sur Enregistrer.
-
Dans le menu de navigation, cliquez sur Audience.
Les utilisateurs tests sont nécessaires lorsque les utilisateurs sont des utilisateurs externes et que l'état de publication est défini sur Test.
-
Cliquez sur + Ajouter des utilisateurs.
-
Dans le panneau de gauche des instructions de l'atelier, copiez à nouveau le nom d'utilisateur.
-
Dans le volet Ajouter des utilisateurs, collez le nom d'utilisateur copié dans le champ prévu à cet effet, puis cliquez sur Enregistrer.
Créer les identifiants OAuth 2.0
-
Dans le menu de navigation, cliquez sur Clients, puis sur + Créer un client.
-
Dans la liste Type d'application, sélectionnez Application Web.
-
Dans le champ Nom, saisissez Bookshelf
.
-
Sous URI de redirection autorisés, cliquez sur + Ajouter un URI.
L'URI spécifié ici sera utilisé lorsque Google redirigera le navigateur vers l'application après que l'utilisateur aura donné son consentement.
-
Pour obtenir l'URI de redirection, exécutez la commande suivante dans Cloud Shell :
echo "https://8080-${WEB_HOST}/oauth2callback"
-
Copiez l'URI créé par la commande echo, puis collez-le dans le champ URI 1.
-
Cliquez sur Créer.
-
Cliquez sur Télécharger au format JSON, puis enregistrez le fichier JSON du code secret du client sur votre machine locale.
Le fichier du code secret du client sera utilisé pour valider votre application auprès de Google.
-
Cliquez sur Fermer.
-
Dans Cloud Shell, cliquez sur Plus (
) dans la barre d'outils en haut à droite, puis sur Importer.
-
Cliquez sur Sélect. fichiers, sélectionnez le fichier JSON du code secret du client, puis cliquez sur Ouvrir.
-
Cliquez sur Importer.
Le fichier JSON du code secret du client est désormais disponible dans le répertoire d'accueil. Le contenu de ce fichier sera utilisé pendant le processus OAuth.
-
Dans Cloud Shell, exécutez la commande suivante :
cat ~/client_secret_*.json
Le contenu JSON inclut la valeur client_secret, qui doit être traitée comme un mot de passe. Par exemple, vous ne devez jamais stocker ce fichier JSON dans un dépôt de code.
Stocker le fichier JSON du code secret du client dans Secret Manager
Secret Manager est un emplacement sécurisé et recommandé où stocker le fichier JSON du code secret du client.
-
Pour activer l'API Secret Manager, exécutez la commande suivante :
gcloud services enable secretmanager.googleapis.com
-
Pour renommer le fichier du code secret du client, exécutez la commande suivante :
mv ~/client_secret*.json ~/client_secret.json
-
Pour créer le secret, exécutez la commande suivante :
gcloud secrets create bookshelf-client-secrets --data-file=$HOME/client_secret.json
Un secret nommé bookshelf-client-secrets
est désormais accessible depuis votre application.
Votre application a également besoin d'une autre valeur de secret : la clé secrète Flask, qui sert à signer les informations dans les cookies.
-
Afin de créer un secret pour la clé secrète Flask, exécutez la commande suivante :
tr -dc A-Za-z0-9 </dev/urandom | head -c 20 | gcloud secrets create flask-secret-key --data-file=-
Cette commande crée un mot de passe alphanumérique aléatoire de 20 caractères, puis le stocke dans un secret nommé flask-secret-key
.
Cliquez sur Vérifier ma progression pour valider l'objectif.
Créer des identifiants d'autorisation OAuth pour votre application
Tâche 3 : Utiliser Secret Manager pour récupérer les secrets dans l'application
Dans cette tâche, vous allez modifier l'application de façon à utiliser Secret Manager.
Modifier le fichier d'exigences pour ajouter Secret Manager
-
Dans nano, ouvrez le fichier requirements.txt
à l'aide de la commande suivante :
nano ~/bookshelf/requirements.txt
-
Dans le fichier d'exigences, utilisez la flèche vers le bas pour accéder à la première ligne vide, puis ajoutez la ligne suivante :
google-cloud-secret-manager==2.24.0
Le fichier requirements.txt devrait maintenant se présenter comme suit :
Flask==3.1.1
gunicorn==23.0.0
google-cloud-logging==3.12.1
google-cloud-firestore==2.21.0
google-cloud-storage==2.17.0
google-cloud-secret-manager==2.24.0
-
Pour enregistrer le fichier et quitter, appuyez sur Ctrl+X, puis sur Y
et sur Entrée.
-
Pour installer les versions mises à jour des dépendances, exécutez la commande suivante :
pip3 install -r ~/bookshelf/requirements.txt --user
Créer une fonction pour récupérer les secrets
Le fichier secrets.py
contient le code permettant de récupérer les secrets à partir de Secret Manager.
-
Pour créer le fichier secrets.py
, exécutez la commande suivante :
cat > ~/bookshelf/secrets.py <<EOF
import os
from google.cloud import secretmanager
def get_secret(secret_id, version_id='latest'):
# create the secret manager client
client = secretmanager.SecretManagerServiceClient()
# build the resource name of the secret version
project_id = os.getenv('GOOGLE_CLOUD_PROJECT')
name = f"projects/{project_id}/secrets/{secret_id}/versions/{version_id}"
# access the secret version
response = client.access_secret_version(name=name)
# return the decoded secret
return response.payload.data.decode('UTF-8')
EOF
La fonction get_secret()
accepte un ID de secret et un ID de version facultatif. Elle renvoie le secret demandé.
Modifier main.py pour utiliser Secret Manager
Le fichier de code main doit appeler Secret Manager pour récupérer les secrets.
-
Dans un éditeur de fichiers, ouvrez le fichier ~/bookshelf/main.py
.
-
Une fois storage
importé, ajoutez la ligne suivante :
import secrets
Cette ligne importe le fichier secrets.py que vous venez de créer.
-
Dans l'appel de la fonction app.config.update, remplacez SECRET_KEY :
SECRET_KEY='secret', # don't store SECRET_KEY in code in a production app
par :
SECRET_KEY=secrets.get_secret('flask-secret-key'),
La clé secrète Flask n'est plus stockée dans le code de l'application.
-
Enregistrez le fichier.
Tâche 4 : Créer des fonctions pour le flux OAuth
Dans cette tâche, vous allez ajouter des fonctions qui gèrent le flux de connexion OAuth.
Lorsqu'un utilisateur se connecte à l'application Web, celle-ci lance la séquence d'autorisation OAuth. OAuth permet à l'utilisateur de s'authentifier et d'autoriser l'accès demandé par l'application. La séquence d'autorisation OAuth se présente comme suit :

La séquence d'autorisation commence lorsque l'application redirige le navigateur vers une URL Google. Google gère l'authentification de l'utilisateur, la sélection de session et le consentement de l'utilisateur. Le résultat est un code d'autorisation, que l'application peut échanger contre un jeton d'accès et un jeton d'actualisation.
L'application stocke le jeton d'actualisation pour une utilisation ultérieure et se sert du jeton d'accès pour accéder aux API Google. L'application Bookshelf appelle une API Google pour récupérer des informations sur l'utilisateur. Lorsque le jeton d'accès expire, l'application utilise le jeton d'actualisation pour obtenir un nouveau jeton d'accès.
Ajouter des dépendances
Le client OAuth Python pour Google nécessite trois autres packages Python.
-
Dans le fichier ~/bookshelf/requirements.txt
, ajoutez les lignes suivantes :
google-api-python-client==2.178.0
google-auth==2.40.3
google-auth-oauthlib==1.2.2
Le fichier requirements.txt devrait maintenant se présenter comme suit :
Flask==3.1.1
gunicorn==23.0.0
google-cloud-logging==3.12.1
google-cloud-firestore==2.21.0
google-cloud-storage==2.17.0
google-cloud-secret-manager==2.24.0
google-api-python-client==2.178.0
google-auth==2.40.3
google-auth-oauthlib==1.2.2
-
Enregistrez le fichier.
-
Pour installer les versions mises à jour des dépendances, exécutez la commande suivante :
pip3 install -r ~/bookshelf/requirements.txt --user
Ajouter des fonctions OAuth pour gérer le flux d'autorisation
Le fichier oauth.py
contient le code permettant de récupérer un jeton OAuth auprès de Google.
-
Pour créer le fichier oauth.py
, exécutez la commande suivante :
cat > ~/bookshelf/oauth.py <<EOF
import google.oauth2.credentials
import google_auth_oauthlib.flow
from uuid import uuid4
from googleapiclient.discovery import build
from werkzeug.exceptions import Unauthorized
def _credentials_to_dict(credentials):
"""
Convert credentials mapping (object) into a dictionary.
"""
return {
'token': credentials.token,
'refresh_token': credentials.refresh_token,
'token_uri': credentials.token_uri,
'client_id': credentials.client_id,
'client_secret': credentials.client_secret,
'scopes': credentials.scopes,
'id_token': credentials.id_token,
}
def authorize(callback_uri, client_config, scopes):
"""
Builds the URL that will be used for redirection to Google
to start the OAuth flow.
"""
# specify the flow configuration details
flow = google_auth_oauthlib.flow.Flow.from_client_config(
client_config=client_config,
scopes=scopes,
)
flow.redirect_uri = callback_uri
# create a random state
state = str(uuid4())
# get the authorization URL
authorization_url, state = flow.authorization_url(
# offline access allows access token refresh without reprompting the user
# using online here to force log in
access_type='online',
state=state,
prompt='consent',
include_granted_scopes='false',
)
return authorization_url, state
def handle_callback(callback_uri, client_config, scopes, request_url, stored_state, received_state):
"""
Fetches credentials using the authorization code in the request URL,
and retrieves user information for the logged-in user.
"""
# validate received state
if received_state != stored_state:
raise Unauthorized(f'Invalid state parameter: received={received_state} stored={stored_state}')
# specify the flow configuration details
flow = google_auth_oauthlib.flow.Flow.from_client_config(
client_config=client_config,
scopes=scopes
)
flow.redirect_uri = callback_uri
# get a token using the details in the request
flow.fetch_token(authorization_response=request_url)
credentials = flow.credentials
oauth2_client = build('oauth2','v2',credentials=credentials, cache_discovery=False)
user_info = oauth2_client.userinfo().get().execute()
return _credentials_to_dict(credentials), user_info
EOF
La fonction authorize()
lance la séquence d'autorisation. Elle configure le flux à l'aide du paramètre client_config transmis, qui sera créé à partir de la chaîne JSON de configuration OAuth stockée en tant que secret. callback_uri indique la cible d'appel de Google avec le code d'autorisation. Cet URI doit correspondre à un URI configuré en tant qu'URI de redirection autorisé pour l'application Bookshelf. L'appel flow.authorization_url()
crée l'URL complète pour la redirection vers Google. Un état est créé et transmis. Il sera stocké dans la session pour associer cet appel au rappel ultérieur. L'URL d'autorisation et l'état sont renvoyés à l'appelant.
La fonction handle_callback()
est utilisée lorsque le rappel est reçu de Google. L'état spécifié dans l'URL de rappel doit correspondre à l'état stocké qui a été envoyé dans l'URL d'autorisation. L'appel flow.fetch_token()
peut alors être utilisé pour extraire les identifiants, y compris les jetons d'actualisation et d'accès. Les identifiants renvoyés servent ensuite à appeler Google et à recevoir les informations de l'utilisateur connecté. Après cela, les identifiants et les informations de l'utilisateur sont renvoyés à l'appelant.
Remarque : La ligne oauth2_client.userinfo() peut afficher un message d'erreur dans votre IDE indiquant qu'il n'y a aucun membre "userinfo". build() renvoie un objet "Resource", et les membres valides ne sont pas connus au moment de la compilation. Vous pouvez ignorer cette erreur.
Tâche 5 : Ajouter des points de terminaison de connexion, de rappel et de déconnexion
Dans cette tâche, vous allez utiliser les fonctions OAuth que vous venez de créer pour implémenter des points de terminaison de connexion, de déconnexion et de rappel.
Modifier les modèles HTML
-
Pour créer un modèle d'erreur, exécutez la commande suivante :
cat > ~/bookshelf/templates/error.html <<EOF
{% extends "base.html" %}
{% block content %}
<h3>Error: {{error_message}}</h3>
{% endblock %}
EOF
Lors de la connexion, l'utilisateur peut rencontrer une erreur. Cette page sera utilisée pour afficher l'erreur.
-
Dans un éditeur de fichiers, ouvrez le fichier ~/bookshelf/templates/base.html
.
Des liens de connexion et de déconnexion seront ajoutés à l'application.
-
Dans la section navbar, sur la ligne après la balise fermante (/ul) de la liste à puces (ul) avec class="nav navbar-nav"
, ajoutez la section suivante :
<ul class="nav navbar-nav navbar-right">
{% if session['credentials'] %}
<div class="navbar-brand">{{session['user'].email}}</div>
<div class="navbar-brand"><a href="/logout">Logout</a></div>
{% else %}
<div class="navbar-brand"><a href="/login">Login</a></div>
{% endif %}
</ul>
Le fichier se présente désormais comme suit :
<!DOCTYPE html>
<html lang="en">
<head>
<title>Bookshelf</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css">
</head>
<body>
<div class="navbar navbar-default">
<div class="container">
<div class="navbar-header">
<div class="navbar-brand">Bookshelf</div>
</div>
<ul class="navbar-nav">
<li><a href="/">Books</a></li>
</ul>
<ul class="nav navbar-nav navbar-right">
{% if session['credentials'] %}
<div class="navbar-brand">{{session['user'].email}}</div>
<div class="navbar-brand"><a href="/logout">Logout</a></div>
{% else %}
<div class="navbar-brand"><a href="/login">Login</a></div>
{% endif %}
</ul>
</div>
</div>
<div class="container">
{% block content %}{% endblock %}
</div>
</body>
</html>
Le modèle de base utilise à présent la session pour vérifier si l'utilisateur est connecté. Si c'est le cas, son adresse e-mail et un lien de déconnexion s'affichent. Si l'utilisateur n'est pas connecté, un lien de connexion apparaît.
-
Enregistrez le fichier.
Modifier les importations
-
Dans un éditeur de fichiers, ouvrez le fichier ~/bookshelf/main.py
.
-
Ajoutez session
aux importations Flask.
Les importations Flask doivent désormais se présenter comme suit :
from flask import current_app, Flask, redirect, render_template
from flask import request, url_for, session
Une session permet d'accéder aux informations associées à l'utilisateur connecté. Les données de session seront stockées dans des cookies.
-
Après la ligne cloud_logging import
, ajoutez les lignes suivantes :
import json
import os
from urllib.parse import urlparse
Dans main.py
, la bibliothèque json
est utilisée pour convertir la chaîne de code secret du client en mappage (objet) et la bibliothèque os
permet d'utiliser les variables d'environnement. La fonction urlparse()
sera utilisée pour remplacer le schéma et le nom d'hôte dans une URL.
-
Une fois secrets
importé, ajoutez la ligne suivante :
import oauth
Vous importez ainsi les fonctions OAuth que vous avez créées.
Ajouter des éléments de configuration
-
Dans l'appel de la fonction app.config.update()
, ajoutez les lignes suivantes après la ligne ALLOWED_EXTENSIONS
:
CLIENT_SECRETS=json.loads(secrets.get_secret('bookshelf-client-secrets')),
SCOPES=[
'openid',
'https://www.googleapis.com/auth/contacts.readonly',
'https://www.googleapis.com/auth/userinfo.email',
'https://www.googleapis.com/auth/userinfo.profile',
],
EXTERNAL_HOST_URL=os.getenv('EXTERNAL_HOST_URL'),
Les éléments de configuration suivants sont ajoutés :
-
CLIENT_SECRETS
contient un mappage (objet) pour la configuration OAuth stockée dans Secret Manager.
-
SCOPES
contient la liste des niveaux d'accès à demander.
-
EXTERNAL_HOST_URL
sert à déterminer l'URL de rappel. Lorsque vous utilisez l'aperçu sur le Web avec Cloud Shell, l'application définie pour s'exécuter en tant que localhost (127.0.0.1) sur le port 80 est exposée à Internet sur https://8080-...-cloudshell.dev
. Cette URL permettra de convertir l'URL localhost du point de terminaison de rappel en URL accessible publiquement. La valeur sera transmise en tant que variable d'environnement.
Ajouter des points de terminaison et des fonctions connexes
-
Après la fonction log_request()
(qui commence par def log_request():
), ajoutez les fonctions suivantes :
def logout_session():
"""
Clears known session items.
"""
session.pop('credentials', None)
session.pop('user', None)
session.pop('state', None)
session.pop('error_message', None)
session.pop('login_return', None)
return
def external_url(url):
"""
Cloud Shell routes https://8080-***/ to localhost over http
This function replaces the localhost host with the configured scheme + hostname
"""
external_host_url = current_app.config['EXTERNAL_HOST_URL']
if external_host_url is None:
# force https
if url.startswith('http://'):
url = f"https://{url[7:]}"
return url
# replace the scheme and hostname with the external host URL
parsed_url = urlparse(url)
replace_string = f"{parsed_url.scheme}://{parsed_url.netloc}"
new_url = f"{external_host_url}{url[len(replace_string):]}"
return new_url
@app.route('/error')
def error():
"""
Display an error.
"""
log_request(request)
if "error_message" not in session:
return redirect(url_for('.list'))
# render error
return render_template('error.html', error_message=session.pop('error_message', None))
@app.route("/login")
def login():
"""
Login if not already logged in.
"""
log_request(request)
if not "credentials" in session:
# need to log in
current_app.logger.info('logging in')
# get authorization URL
authorization_url, state = oauth.authorize(
callback_uri=external_url(url_for('oauth2callback', _external=True)),
client_config=current_app.config['CLIENT_SECRETS'],
scopes=current_app.config['SCOPES'])
current_app.logger.info(f"authorization_url={authorization_url}")
# save state for verification on callback
session['state'] = state
return redirect(authorization_url)
# already logged in
return redirect(session.pop('login_return', url_for('.list')))
@app.route("/oauth2callback")
def oauth2callback():
"""
Callback destination during OAuth process.
"""
log_request(request)
# check for error, probably access denied by user
error = request.args.get('error', None)
if error:
session['error_message'] = f"{error}"
return redirect(url_for('.error'))
# handle the OAuth2 callback
credentials, user_info = oauth.handle_callback(
callback_uri=external_url(url_for('oauth2callback', _external=True)),
client_config=current_app.config['CLIENT_SECRETS'],
scopes=current_app.config['SCOPES'],
request_url=external_url(request.url),
stored_state=session.pop('state', None),
received_state=request.args.get('state', ''))
session['credentials'] = credentials
session['user'] = user_info
current_app.logger.info(f"user_info={user_info}")
return redirect(session.pop('login_return', url_for('.list')))
@app.route("/logout")
def logout():
"""
Log out and return to root page.
"""
log_request(request)
logout_session()
return redirect(url_for('.list'))
La fonction logout_session()
efface les entrées de session connues.
La fonction external_url()
remplace le schéma et le nom d'hôte d'une URL par un autre nom d'hôte pour l'accès externe. Si l'hôte de remplacement n'est pas spécifié, la fonction s'assure que l'URL renvoyée utilise "https".
Le point de terminaison /error
sert à afficher une erreur.
Le point de terminaison /login
vérifie la session pour déterminer si un utilisateur est connecté. Un utilisateur est connecté si des identifiants sont stockés dans la session. Si l'utilisateur n'est pas connecté, la fonction oauth.authorize()
est appelée pour obtenir l'URL d'autorisation et l'état de la redirection vers Google. L'état est enregistré dans la session, puis le navigateur est redirigé vers l'URL d'autorisation.
Le point de terminaison /oauth2callback
est appelé par Google pendant le processus d'autorisation. En cas d'erreur, le processus échoue et l'utilisateur est redirigé vers la page d'erreur. Si aucune erreur n'est détectée, la fonction handle_callback()
est appelée pour récupérer le jeton et les informations de l'utilisateur. À la fin du processus, l'utilisateur est redirigé vers la page précédente où la connexion a été lancée automatiquement ou vers la page racine (liste des livres) s'il n'y a pas d'emplacement de retour.
Le point de terminaison /logout
déconnecte l'utilisateur en supprimant les identifiants et les données utilisateur de la session, puis revient à la page racine.
Forcer la connexion pour ajouter, modifier ou supprimer des livres
Un utilisateur peut parcourir les livres de l'application Bookshelf sans se connecter. Toutefois, il est logique d'obliger l'utilisateur à se connecter avant de pouvoir modifier les livres.
Lorsqu'un utilisateur tente d'ajouter, de modifier ou de supprimer un livre sans être connecté, il doit y être invité.
-
Dans la fonction add()
, ajoutez les lignes suivantes juste après l'appel à log_request()
:
# must be logged in
if "credentials" not in session:
session['login_return'] = url_for('.add')
return redirect(url_for('.login'))
Dans add()
, si l'utilisateur n'est pas connecté, il est redirigé vers la page d'ajout après s'être connecté.
-
Dans la fonction edit()
, ajoutez les lignes suivantes juste après l'appel à log_request()
:
# must be logged in
if "credentials" not in session:
session['login_return'] = url_for('.edit', book_id=book_id)
return redirect(url_for('.login'))
Dans edit()
, si l'utilisateur n'est pas connecté, il est redirigé vers la page de modification du livre après s'être connecté.
-
Dans la fonction delete()
, ajoutez les lignes suivantes juste après l'appel à log_request()
:
# must be logged in
if "credentials" not in session:
session['login_return'] = url_for('.view', book_id=book_id)
return redirect(url_for('.login'))
Dans delete()
, si l'utilisateur n'est pas connecté, il est redirigé vers la page de vue du livre après s'être connecté.
-
Enregistrez le fichier.
Tester l'application
-
Pour démarrer le serveur HTTP, exécutez la commande suivante dans Cloud Shell :
cd ~/bookshelf; EXTERNAL_HOST_URL="https://8080-$WEB_HOST" ~/.local/bin/gunicorn -b :8080 main:app
Une variable d'environnement est transmise à l'application :
-
EXTERNAL_HOST_URL
spécifie le schéma et le nom d'hôte à utiliser dans l'URL de rappel. Si cette variable d'environnement n'est pas spécifiée, le paramètre redirect_uri transmis à Google dans l'URL d'autorisation utilisera le nom d'hôte que l'application voit dans les URL entrantes : 127.0.0.1:8080
(c'est-à-dire localhost). L'aperçu sur le Web transfère les requêtes de l'URL cloudshell.dev vers localhost (http://127.0.0.1:8080).
Remarque : Si un message vous demande d'autoriser Cloud Shell, cliquez sur Autoriser.
-
Pour ouvrir l'application dans le navigateur Web, cliquez sur Aperçu sur le Web, puis sélectionnez Prévisualiser sur le port 8080.

Un nouvel onglet s'ouvre dans le navigateur et l'application s'exécute. Le livre Le Magicien d'Oz doit s'afficher. L'utilisateur n'est pas connecté.
-
Cliquez sur + Ajouter un livre.
Comme vous devez être connecté pour ajouter un livre, vous devez choisir un compte pour vous connecter avec Google :

-
Cliquez sur l'adresse e-mail du participant, puis sur Continuer.
Google obtiendra désormais un consentement pour tout niveau d'accès restreint ou non sensible demandé. Dans ce cas, télécharger tous vos contacts est niveau d'accès sensible.

-
Cliquez sur Autoriser.
Vous êtes redirigé vers l'application, sur la page Ajouter un livre. Vous êtes connecté, et votre adresse e-mail s'affiche en haut à droite. Si vous examinez les journaux dans Cloud Shell, vous devriez voir l'appel de rappel de Google :
INFO:main:REQ: GET http://127.0.0.1:8080/oauth2callback?state=88789b07-2474-423f-b572-f5d4a3240ace&code=4g0AfJohXm0vtB2eYHnRaAeM8m-VCmnssg5YgrjoJstTLmHaVq8nlbJo5uzIS67NbWTXTOqDw&scope=email%20profile%20openid%20https://www.googleapis.com/auth/contacts.readonly%20https://www.googleapis.com/auth/userinfo.email%20https://www.googleapis.com/auth/userinfo.profile&authuser=0&hd=qwiklabs.net&prompt=consent
L'utilisateur a autorisé l'accès. Le paramètre code
contient donc le code d'autorisation qui a ensuite été échangé contre les identifiants. Les niveaux d'accès autorisés sont également renvoyés.
-
Cliquez sur Livres, puis sur + Ajouter un livre.
Puisque vous êtes déjà connecté, vous pouvez accéder directement à la page Ajouter un livre.
-
Cliquez sur Déconnexion, puis sur Connexion.
-
Cliquez sur l'adresse e-mail du participant, puis sur Continuer et Annuler.
Vous êtes redirigé vers la page d'erreur. Examinez les journaux dans Cloud Shell. Vous devriez voir le rappel effectué par Google, qui doit ressembler à ceci :
INFO:main:REQ: GET http://127.0.0.1:8080/oauth2callback?error=access_denied&state=72342071-c8dc-43be-8184-9f6bd6069cd5
Dans ce cas, le consentement n'a pas été donné. Le code d'autorisation n'a donc pas été renvoyé et l'application ne peut pas obtenir les identifiants de l'utilisateur.
-
Dans Cloud Shell, pour quitter l'application, appuyez sur Ctrl+C
.
Cliquez sur Vérifier ma progression pour valider l'objectif.
Ajouter des points de terminaison de connexion, de rappel et de déconnexion
Tâche 6 : Créer des fonctions de traduction
Dans cette tâche, vous allez créer des fonctions qui utilisent l'API Cloud Translation pour détecter la langue du texte et le traduire.
Les appels de l'API Cloud Translation utilisent les identifiants de l'application.
Ajouter une dépendance Cloud Translation
L'application nécessite un autre package Python.
-
Dans le fichier ~/bookshelf/requirements.txt
, ajoutez la ligne suivante :
google-cloud-translate==3.21.1
Le fichier requirements.txt devrait maintenant se présenter comme suit :
Flask==3.1.1
gunicorn==23.0.0
google-cloud-logging==3.12.1
google-cloud-firestore==2.21.0
google-cloud-storage==2.17.0
google-cloud-secret-manager==2.24.0
google-api-python-client==2.178.0
google-auth==2.40.3
google-auth-oauthlib==1.2.2
google-cloud-translate==3.21.1
-
Enregistrez le fichier.
-
Pour installer les dépendances mises à jour, exécutez la commande suivante :
pip3 install -r ~/bookshelf/requirements.txt --user
Ajouter des fonctions de traduction
Le fichier translate.py
contient le code permettant d'effectuer la traduction.
-
Pour créer le fichier translate.py
, exécutez la commande suivante :
cat > ~/bookshelf/translate.py <<EOF
import os
from google.cloud import translate
PROJECT_ID = os.getenv('GOOGLE_CLOUD_PROJECT')
PARENT = f"projects/{PROJECT_ID}"
supported_languages = None
def get_languages():
"""
Gets the list of supported languages.
"""
# use the global variable
global supported_languages
# retrieve supported languages if not previously retrieved
if not supported_languages:
client = translate.TranslationServiceClient()
response = client.get_supported_languages(
parent=PARENT,
display_language_code='en',
)
supported_languages = response.languages
return supported_languages
def detect_language(text):
"""
Detect the language of the supplied text.
Returns the most likely language.
"""
client = translate.TranslationServiceClient()
response = client.detect_language(
parent=PARENT,
content=text,
)
return response.languages[0]
def translate_text(text, target_language_code):
"""
Translate the text to the target language.
"""
client = translate.TranslationServiceClient()
response = client.translate_text(
parent=PARENT,
contents=[text],
target_language_code=target_language_code,
)
return response.translations[0]
EOF
La fonction get_languages()
récupère la liste des langues acceptées par l'API Cloud Translation. Chaque langue de la liste présente un ID (language_code) et le texte à afficher (display_name).
La fonction detect_language()
détecte la langue d'une chaîne de texte.
La fonction translate_language()
traduit le texte dans une langue donnée.
Tâche 7 : Créer un profil utilisateur pour la sélection de la langue et traduire les descriptions
Dans cette tâche, vous allez créer un profil utilisateur pour les utilisateurs connectés. L'utilisateur peut sélectionner sa langue préférée.
Le profil sera stocké dans une collection Firestore nommée profiles
. Un profil par défaut avec l'anglais comme langue préférée sera utilisé jusqu'à ce que l'utilisateur mette à jour le profil.
Ajouter des fonctions pour lire et mettre à jour les profils
Le fichier profiledb.py
contient le code permettant de lire et de mettre à jour les profils utilisateur. L'adresse e-mail de l'utilisateur servira de clé de profil. Dans cette implémentation, le seul élément du profil sera la langue préférée.
-
Pour créer le fichier profiledb.py
, exécutez la commande suivante :
cat > ~/bookshelf/profiledb.py <<EOF
from google.cloud import firestore
default_profile = { "preferredLanguage": "en" }
def __document_to_dict(doc):
if not doc.exists:
return None
doc_dict = doc.to_dict()
doc_dict['id'] = doc.id
return doc_dict
def read(email):
"""
Return a profile by email.
"""
db = firestore.Client()
# retrieve a profile from the database by ID
profile_ref = db.collection("profiles").document(email)
profile_dict = __document_to_dict(profile_ref.get())
# return empty dictionary if no profile
if profile_dict is None:
profile_dict = default_profile.copy()
return profile_dict
def read_entry(email, key, default_value=''):
"""
Return a profile entry by email and key.
"""
profile_dict = read(email)
return profile_dict.get(key, default_value)
def update(data, email):
"""
Update a profile, and return the updated profile's details.
"""
db = firestore.Client()
# update profile in database
profile_ref = db.collection("profiles").document(email)
profile_ref.set(data)
return __document_to_dict(profile_ref.get())
EOF
La fonction read()
récupère le profil d'un utilisateur spécifié. Si aucun profil n'est trouvé, une copie du profil par défaut est renvoyée.
La fonction read_entry()
renvoie une seule valeur à partir du profil d'un utilisateur. Si la clé est introuvable dans le profil de l'utilisateur, la valeur par défaut transmise est renvoyée à la place.
La fonction update()
crée ou écrase le profil de l'utilisateur avec les données spécifiées.
Ajouter le point de terminaison "profile" pour afficher et modifier un profil utilisateur
-
Afin de créer un modèle pour le profil utilisateur dans profile.html
, exécutez la commande suivante :
cat > ~/bookshelf/templates/profile.html <<EOF
{# [START form] #}
{% extends "base.html" %}
{% block content %}
<h3>Profile for {{session['user']['email']}}</h3>
<form method="POST" enctype="multipart/form-data">
<div class="form-group">
<label for="preferredLanguage">Preferred Language</label>
<select id="preferredLanguage" name="preferredLanguage">
{% for l in languages %}
{% if l.language_code == profile['preferredLanguage'] %}
<option value="{{l.language_code}}" selected>{{l.display_name}}</option>
{% else %}
<option value="{{l.language_code}}">{{l.display_name}}</option>
{% endif %}
{% endfor %}
</select>
</div>
<button type="submit" class="btn btn-success">Save</button>
</form>
{% endblock %}
{# [END form] #}
EOF
Ce modèle crée un formulaire unique avec une commande de sélection et un bouton d'envoi. La commande de sélection est chargée avec toutes les langues transmises à l'aide de la variable de liste languages
. La valeur de chaque entrée est language_code
, et le nom display_name
est indiqué dans la commande de sélection. La langue affichée au départ est la langue preferredLanguage
spécifiée dans le profil.
-
Dans un éditeur de fichiers, ouvrez le fichier ~/bookshelf/main.py
.
-
Une fois oauth
importé, ajoutez les lignes suivantes :
import translate
import profiledb
Vous importez ainsi les fichiers translate.py et profiledb.py que vous venez de créer.
-
Pour ajouter le point de terminaison /profile
, ajoutez la fonction suivante après le point de terminaison /books/<book_id>/delete
:
@app.route('/profile', methods=['GET', 'POST'])
def profile():
"""
If GET, show the form to collect updated details for the user profile.
If POST, update the profile based on the specified form.
"""
log_request(request)
# must be logged in
if "credentials" not in session:
session['login_return'] = url_for('.profile')
return redirect(url_for('.login'))
# read existing profile
email = session['user']['email']
profile = profiledb.read(email)
# Save details if form was posted
if request.method == 'POST':
# get book details from form
data = request.form.to_dict(flat=True)
# update profile
profiledb.update(data, email)
session['preferred_language'] = data['preferredLanguage']
# return to root
return redirect(url_for('.list'))
# render form to update book
return render_template('profile.html', action='Edit',
profile=profile, languages=translate.get_languages())
Le profil n'est accessible qu'aux utilisateurs connectés. Si l'utilisateur n'est pas connecté, il est redirigé vers la page de connexion.
L'adresse e-mail de l'utilisateur connecté est extraite des informations de l'utilisateur dans la session, puis le profil actuel est lu.
Le profil est affiché à l'aide du modèle profile.html.
Une fois que vous avez cliqué sur le bouton d'envoi, le profil est mis à jour dans la base de données, la langue préférée de l'utilisateur est stockée dans la session et le navigateur est redirigé vers la page racine.
-
Enregistrez le fichier.
Accéder au profil en cliquant sur l'adresse e-mail de l'utilisateur
-
Dans un éditeur de fichiers, ouvrez le fichier ~/bookshelf/templates/base.html
.
-
Dans ce fichier, remplacez la ligne suivante :
<div class="navbar-brand">{{session['user'].email}}</div>
par :
<div class="navbar-brand"><a href="/profile">{{session['user'].email}}</a></div>
L'adresse e-mail affichée est alors remplacée par un lien cliquable qui redirige vers le point de terminaison /profile
.
-
Enregistrez le fichier.
Traduire la description sur la page de vue
-
Dans un éditeur de fichiers, ouvrez le fichier ~/bookshelf/templates/view.html
.
-
Dans ce fichier, remplacez la ligne suivante :
<p class="book-description">{{book.description}}</p>
par :
{% if translation_language is not none %}
<p class="book-description"><strong>Description ({{description_language}}): </strong>{{book.description}}</p>
<p class="book-description"><strong>Translation ({{translation_language}}): </strong>{{translated_text}}</p>
{% else %}
<p class="book-description"><strong>Description: </strong>{{book.description}}</p>
{% endif %}
Si la valeur translation_language n'est pas spécifiée, la description ne change pas. Toutefois, si une langue de traduction est indiquée, la langue de la description d'origine est affichée, et la version traduite du texte est visible sur la ligne suivante. Le point de terminaison de vue doit transmettre ces informations supplémentaires.
-
Enregistrez le fichier.
-
Dans un éditeur de fichiers, ouvrez le fichier ~/bookshelf/main.py
.
-
Après la fonction log_request()
(qui commence par def log_request():
), ajoutez le code suivant :
# build a mapping of language codes to display names
display_languages = {}
for l in translate.get_languages():
display_languages[l.language_code] = l.display_name
La fonction detect_language() renvoie le code de langue détecté, mais pas le nom à afficher. Ce code crée un mappage entre le code de langue et le nom à afficher. Il sera utilisé pour afficher la langue détectée dans le modèle de vue.
-
Remplacez le code du point de terminaison de vue complet par le code suivant :
@app.route('/books/<book_id>')
def view(book_id):
"""
View the details of a specified book.
"""
log_request(request)
# retrieve a specific book
book = booksdb.read(book_id)
current_app.logger.info(f"book={book}")
# defaults if logged out
description_language = None
translation_language = None
translated_text = ''
if book['description'] and "credentials" in session:
preferred_language = session.get('preferred_language', 'en')
# translate description
translation = translate.translate_text(
text=book['description'],
target_language_code=preferred_language,
)
description_language = display_languages[translation.detected_language_code]
translation_language = display_languages[preferred_language]
translated_text = translation.translated_text
# render book details
return render_template('view.html', book=book,
translated_text=translated_text,
description_language=description_language,
translation_language=translation_language,
)
Le code traduit désormais la description du livre dans la langue préférée de l'utilisateur, puis transmet la traduction et les langues au modèle.
-
Enregistrez le fichier.
Tâche 8 : Tester l'application
-
Pour démarrer le serveur HTTP, exécutez la commande suivante :
cd ~/bookshelf; EXTERNAL_HOST_URL="https://8080-$WEB_HOST" ~/.local/bin/gunicorn -b :8080 main:app
-
Pour ouvrir l'application dans le navigateur Web, cliquez sur Aperçu sur le Web, puis sélectionnez Prévisualiser sur le port 8080.

Un nouvel onglet s'ouvre dans le navigateur et l'application s'exécute. Le livre Le Magicien d'Oz doit s'afficher.
Remarque : Si un message vous demande d'autoriser Cloud Shell, cliquez sur Autoriser.
-
Si l'utilisateur n'est pas connecté, cliquez sur Connexion, puis connectez-le en lui demandant son autorisation.
L'adresse e-mail doit désormais être un lien.
-
Cliquez sur l'adresse e-mail.
Le profil est affiché. La commande de sélection de la langue doit afficher English
.
-
Définissez la langue préférée sur Swahili, puis cliquez sur Enregistrer.
-
Cliquez sur le livre Le Magicien d'Oz.
La page de vue contient désormais à la fois la description d'origine en anglais et la traduction en swahili.
Cliquez sur Vérifier ma progression pour valider l'objectif.
Tester l'application
Félicitations !
Vous avez modifié une application de façon à utiliser OAuth pour la connexion des utilisateurs. Vous avez ensuite ajouté un profil utilisateur avec une langue préférée, et vous vous êtes servi de l'API Cloud Translation pour fournir des traductions de descriptions de livres.
Étapes suivantes et informations supplémentaires
Terminer l'atelier
Une fois l'atelier terminé, cliquez sur Terminer l'atelier. Google Cloud Skills Boost supprime les ressources que vous avez utilisées, puis efface le compte.
Si vous le souhaitez, vous pouvez noter l'atelier. Sélectionnez un nombre d'étoiles, saisissez un commentaire, puis cliquez sur Envoyer.
Le nombre d'étoiles correspond à votre degré de satisfaction :
- 1 étoile = très insatisfait(e)
- 2 étoiles = insatisfait(e)
- 3 étoiles = ni insatisfait(e), ni satisfait(e)
- 4 étoiles = satisfait(e)
- 5 étoiles = très satisfait(e)
Si vous ne souhaitez pas donner votre avis, vous pouvez fermer la boîte de dialogue.
Pour soumettre des commentaires, suggestions ou corrections, veuillez accéder à l'onglet Assistance.
Copyright 2024 Google LLC Tous droits réservés. Google et le logo Google sont des marques de Google LLC. Tous les autres noms de société et de produit peuvent être des marques des sociétés auxquelles ils sont associés.