1. Présentation
La série d'ateliers de programmation Serverless Migration Station (tutoriels pratiques à suivre à votre rythme) et les vidéos associées sont destinées à aider les développeurs Google Cloud sans serveur à moderniser leurs applications en les guidant tout au long d'une ou plusieurs migrations, principalement en les aidant à abandonner les anciens services. Cela rend vos applications plus portables et vous offre plus d'options et de flexibilité, ce qui vous permet de vous intégrer à une plus large gamme de produits Cloud et d'y accéder, et de passer plus facilement aux versions linguistiques plus récentes. Bien qu'elle se concentre initialement sur les premiers utilisateurs de Cloud, principalement les développeurs App Engine (environnement standard), cette série est suffisamment large pour inclure d'autres plates-formes sans serveur comme Cloud Functions et Cloud Run, ou ailleurs si nécessaire.
Cet atelier de programmation du module 15 explique comment ajouter l'utilisation d'App Engine blobstore à l'application exemple du module 0. Vous serez alors prêt à migrer cette utilisation vers Cloud Storage dans le module 16.
Vous apprendrez à
- Ajouter l'utilisation de l'API/bibliothèque Blobstore d'App Engine
- Stocker les importations des utilisateurs dans le service
blobstore - Préparer la prochaine étape de la migration vers Cloud Storage
Prérequis
- Un projet Google Cloud Platform avec un compte de facturation GCP actif
- Des connaissances de base en Python
- Une connaissance correcte des commandes Linux courantes
- Des connaissances de base du développement et du déploiement d'applications App Engine
- Une application de module 0 App Engine fonctionnelle (à récupérer depuis le dépôt)
Enquête
Comment allez-vous utiliser ce tutoriel ?
Quel est votre niveau d'expérience avec Python ?
Quel est votre niveau d'expérience avec les services Google Cloud ?
2. Arrière-plan
Pour migrer depuis l'API Blobstore d'App Engine, ajoutez son utilisation à l'application ndb App Engine de référence existante du module 0. L'application exemple affiche les dix visites les plus récentes de l'utilisateur. Nous modifions l'application pour inviter l'utilisateur final à importer un artefact (un fichier) correspondant à sa "visite". Si l'utilisateur ne le souhaite pas, il peut ignorer cette étape. Quelle que soit la décision de l'utilisateur, la page suivante affiche le même résultat que l'application du module 0 (et de nombreux autres modules de cette série). Maintenant que cette intégration blobstore App Engine est implémentée, nous pouvons la migrer vers Cloud Storage dans le prochain atelier de programmation (module 16).
App Engine donne accès aux systèmes de création de modèles Django et Jinja2. L'une des différences de cet exemple (en plus de l'ajout de l'accès à Blobstore) est qu'il passe de Django dans le module 0 à Jinja2 dans le module 15. Une étape clé de la modernisation des applications App Engine consiste à migrer les frameworks Web de webapp2 vers Flask. Ce dernier utilise Jinja2 comme système de conception de modèles par défaut. Nous allons donc commencer à nous orienter dans cette direction en implémentant Jinja2 tout en restant sur webapp2 pour l'accès à Blobstore. Comme Flask utilise Jinja2 par défaut, cela signifie qu'aucune modification du modèle ne sera nécessaire dans le module 16.
3. Configuration/Préparation
Avant de passer à la partie principale du tutoriel, configurez votre projet, obtenez le code et déployez l'application de base pour commencer avec un code fonctionnel.
1. Configurer le projet
Si vous avez déjà déployé l'application du module 0, nous vous recommandons de réutiliser le même projet (et le même code). Vous pouvez également créer un projet ou réutiliser un autre projet existant. Assurez-vous que le projet dispose d'un compte de facturation actif et qu'App Engine est activé.
2. Obtenir un exemple d'application de référence
L'une des conditions préalables à cet atelier de programmation est de disposer d'un exemple d'application fonctionnel du Module 0. Si vous n'en avez pas, vous pouvez l'obtenir à partir du dossier "START" du Module 0 (lien ci-dessous). Cet atelier de programmation vous guide pour chaque étape jusqu'à obtenir un code similaire à celui du dossier "FINISH" du module 15.
- START : Dossier du module 0 (Python 2)
- FINISH : Dossier du module 15 (Python 2)
- Dépôt complet (pour cloner ou télécharger le fichier ZIP)
Le répertoire des fichiers de départ du module 0 doit se présenter comme suit :
$ ls README.md index.html app.yaml main.py
3. (Re)Déployer l'application de référence
Étapes préliminaires restantes :
- Familiarisez-vous avec l'outil de ligne de commande
gcloud - Redéployez l'exemple d'application avec
gcloud app deploy - Vérifier que l'application s'exécute sans problème sur App Engine
Une fois ces étapes effectuées et que vous avez vérifié que votre application Web fonctionne (avec un résultat semblable à celui ci-dessous), vous êtes prêt à ajouter l'utilisation de la mise en cache à votre application.

4. Mettre à jour les fichiers de configuration
app.yaml
La configuration de l'application ne subit aucune modification importante. Toutefois, comme mentionné précédemment, nous passons des modèles Django (par défaut) à Jinja2. Pour effectuer la transition, les utilisateurs doivent donc spécifier la dernière version de Jinja2 disponible sur les serveurs App Engine. Pour ce faire, ils doivent l'ajouter à la section des bibliothèques tierces intégrées de app.yaml.
AVANT :
runtime: python27
threadsafe: yes
api_version: 1
handlers:
- url: /.*
script: main.app
Modifiez votre fichier app.yaml en ajoutant une section libraries comme suit :
APRÈS :
runtime: python27
threadsafe: yes
api_version: 1
handlers:
- url: /.*
script: main.app
libraries:
- name: jinja2
version: latest
Aucun autre fichier de configuration n'a besoin d'être mis à jour. Passons donc aux fichiers d'application.
5. Modifier les fichiers d'application
Importations et compatibilité avec Jinja2
Le premier ensemble de modifications pour main.py inclut l'ajout de l'utilisation de l'API Blobstore et le remplacement des modèles Django par Jinja2. Voici ce qui va changer :
- L'objectif du module
osest de créer un nom de chemin d'accès à un modèle Django. Étant donné que nous passons à Jinja2, où cette opération est gérée, l'utilisation deosainsi que du moteur de rendu de modèle Django,google.appengine.ext.webapp.template, n'est plus nécessaire. Nous les supprimons donc. - Importez l'API Blobstore :
google.appengine.ext.blobstore - Importez les gestionnaires Blobstore trouvés dans le framework
webappd'origine. Ils ne sont pas disponibles danswebapp2:google.appengine.ext.webapp.blobstore_handlers - Importer la compatibilité Jinja2 à partir du package
webapp2_extras
AVANT :
import os
import webapp2
from google.appengine.ext import ndb
from google.appengine.ext.webapp import template
Implémentez les modifications de la liste ci-dessus en remplaçant la section d'importation actuelle dans main.py par l'extrait de code ci-dessous.
APRÈS :
import webapp2
from webapp2_extras import jinja2
from google.appengine.ext import blobstore, ndb
from google.appengine.ext.webapp import blobstore_handlers
Après les importations, ajoutez du code passe-partout pour prendre en charge l'utilisation de Jinja2, comme défini dans la documentation webapp2_extras. L'extrait de code suivant encapsule la classe de gestionnaire de requêtes webapp2 standard avec la fonctionnalité Jinja2. Ajoutez donc ce bloc de code à main.py juste après les importations :
class BaseHandler(webapp2.RequestHandler):
'Derived request handler mixing-in Jinja2 support'
@webapp2.cached_property
def jinja2(self):
return jinja2.get_jinja2(app=self.app)
def render_response(self, _template, **context):
self.response.write(self.jinja2.render_template(_template, **context))
Ajouter la prise en charge de Blobstore
Contrairement aux autres migrations de cette série, où nous conservons la fonctionnalité ou la sortie de l'application exemple identiques (ou presque identiques) sans (trop) modifier l'UX, cet exemple s'éloigne plus radicalement de la norme. Au lieu d'enregistrer immédiatement une nouvelle visite, puis d'afficher les dix dernières, nous mettons à jour l'application pour demander à l'utilisateur un artefact de fichier pour enregistrer sa visite. Les utilisateurs finaux peuvent ensuite importer un fichier correspondant ou sélectionner "Ignorer" pour ne rien importer du tout. Une fois cette étape terminée, la page "Visites les plus récentes" s'affiche.
Cette modification permet à notre application d'utiliser le service Blobstore pour stocker (et éventuellement afficher ultérieurement) cette image ou un autre type de fichier sur la page des visites récentes.
Mettre à jour le modèle de données et l'implémenter
Nous stockons davantage de données, en particulier en mettant à jour le modèle de données pour stocker l'ID (appelé "BlobKey") du fichier importé dans Blobstore et en ajoutant une référence pour l'enregistrer dans store_visit(). Étant donné que ces données supplémentaires sont renvoyées avec tout le reste lors de la requête, fetch_visits() reste le même.
Voici les avant/après de ces modifications avec file_blob, un ndb.BlobKeyProperty :
AVANT :
class Visit(ndb.Model):
'Visit entity registers visitor IP address & timestamp'
visitor = ndb.StringProperty()
timestamp = ndb.DateTimeProperty(auto_now_add=True)
def store_visit(remote_addr, user_agent):
'create new Visit entity in Datastore'
Visit(visitor='{}: {}'.format(remote_addr, user_agent)).put()
def fetch_visits(limit):
'get most recent visits'
return Visit.query().order(-Visit.timestamp).fetch(limit)
APRÈS :
class Visit(ndb.Model):
'Visit entity registers visitor IP address & timestamp'
visitor = ndb.StringProperty()
timestamp = ndb.DateTimeProperty(auto_now_add=True)
file_blob = ndb.BlobKeyProperty()
def store_visit(remote_addr, user_agent, upload_key):
'create new Visit entity in Datastore'
Visit(visitor='{}: {}'.format(remote_addr, user_agent),
file_blob=upload_key).put()
def fetch_visits(limit):
'get most recent visits'
return Visit.query().order(-Visit.timestamp).fetch(limit)
Voici une représentation visuelle des modifications apportées jusqu'à présent :

Importer des fichiers
La modification la plus importante des fonctionnalités concerne la prise en charge de l'importation de fichiers, qu'il s'agisse d'inviter l'utilisateur à importer un fichier, de prendre en charge la fonctionnalité "Ignorer" ou d'afficher un fichier correspondant à une visite. Tout cela fait partie du tableau. Voici les modifications requises pour prendre en charge l'importation de fichiers :
- La requête du gestionnaire principal
GETne récupère plus les visites les plus récentes pour les afficher. Au lieu de cela, il invite l'utilisateur à importer un fichier. - Lorsqu'un utilisateur final envoie un fichier à importer ou ignore ce processus, un
POSTdu formulaire transmet le contrôle au nouveauUploadHandler, dérivé degoogle.appengine.ext.webapp.blobstore_handlers.BlobstoreUploadHandler. - La méthode
POSTdeUploadHandlereffectue l'importation, appellestore_visit()pour enregistrer la visite et déclenche une redirection HTTP 307 pour renvoyer l'utilisateur vers "/", où… - La méthode
POSTdu gestionnaire principal interroge (viafetch_visits()) et affiche les visites les plus récentes. Si l'utilisateur sélectionne "Ignorer", aucun fichier n'est importé, mais la visite est tout de même enregistrée, suivie de la même redirection. - L'affichage des visites les plus récentes inclut un nouveau champ qui s'affiche pour l'utilisateur. Il s'agit d'un lien hypertexte "Afficher" si un fichier à importer est disponible, ou "Aucun" dans le cas contraire. Ces modifications sont apportées au modèle HTML, avec l'ajout d'un formulaire d'importation (plus d'informations à venir).
- Si un utilisateur final clique sur le lien "Afficher" pour une visite avec une vidéo importée, une requête
GETest envoyée à un nouveauViewBlobHandler, dérivé degoogle.appengine.ext.webapp.blobstore_handlers.BlobstoreDownloadHandler. Le fichier est alors affiché s'il s'agit d'une image (dans le navigateur si celui-ci est compatible), une invite de téléchargement s'affiche dans le cas contraire, ou une erreur HTTP 404 est renvoyée si le fichier est introuvable. - En plus de la nouvelle paire de classes de gestionnaires et de la nouvelle paire de routes pour y envoyer le trafic, le gestionnaire principal a besoin d'une nouvelle méthode
POSTpour recevoir la redirection 307 décrite ci-dessus.
Avant ces mises à jour, l'application du module 0 ne comportait qu'un gestionnaire principal avec une méthode GET et un seul itinéraire :
AVANT :
class MainHandler(webapp2.RequestHandler):
'main application (GET) handler'
def get(self):
store_visit(self.request.remote_addr, self.request.user_agent)
visits = fetch_visits(10)
tmpl = os.path.join(os.path.dirname(__file__), 'index.html')
self.response.out.write(template.render(tmpl, {'visits': visits}))
app = webapp2.WSGIApplication([
('/', MainHandler),
], debug=True)
Avec ces mises à jour implémentées, il existe désormais trois gestionnaires : 1) un gestionnaire d'importation avec une méthode POST, 2) un gestionnaire de téléchargement "Afficher le blob" avec une méthode GET et 3) le gestionnaire principal avec les méthodes GET et POST. Apportez ces modifications pour que le reste de votre application ressemble à ce qui suit.
APRÈS :
class UploadHandler(blobstore_handlers.BlobstoreUploadHandler):
'Upload blob (POST) handler'
def post(self):
uploads = self.get_uploads()
blob_id = uploads[0].key() if uploads else None
store_visit(self.request.remote_addr, self.request.user_agent, blob_id)
self.redirect('/', code=307)
class ViewBlobHandler(blobstore_handlers.BlobstoreDownloadHandler):
'view uploaded blob (GET) handler'
def get(self, blob_key):
self.send_blob(blob_key) if blobstore.get(blob_key) else self.error(404)
class MainHandler(BaseHandler):
'main application (GET/POST) handler'
def get(self):
self.render_response('index.html',
upload_url=blobstore.create_upload_url('/upload'))
def post(self):
visits = fetch_visits(10)
self.render_response('index.html', visits=visits)
app = webapp2.WSGIApplication([
('/', MainHandler),
('/upload', UploadHandler),
('/view/([^/]+)?', ViewBlobHandler),
], debug=True)
Ce code que nous venons d'ajouter comporte plusieurs appels clés :
- Dans
MainHandler.get, il y a un appel àblobstore.create_upload_url. Cet appel génère l'URL vers laquelle le formulairePOSTenvoie le fichier au gestionnaire d'importation pour qu'il l'envoie à Blobstore. - Dans
UploadHandler.post, il y a un appel àblobstore_handlers.BlobstoreUploadHandler.get_uploads. C'est là que la magie opère : le fichier est placé dans Blobstore et un ID unique et persistant lui est attribué, sonBlobKey. - Dans
ViewBlobHandler.get, l'appel deblobstore_handlers.BlobstoreDownloadHandler.sendavec leBlobKeyd'un fichier entraîne la récupération du fichier et son transfert vers le navigateur de l'utilisateur final.
Ces appels représentent la majeure partie de l'accès aux fonctionnalités ajoutées à l'application. Voici une représentation visuelle de ce deuxième et dernier ensemble de modifications apportées à main.py :

Mettre à jour le modèle HTML
Certaines mises à jour de l'application principale affectent l'interface utilisateur de l'application. Des modifications correspondantes sont donc nécessaires dans le modèle Web, deux en fait :
- Un formulaire d'importation de fichier est requis avec trois éléments d'entrée : un fichier et une paire de boutons d'envoi pour l'importation de fichier et l'option "Ignorer", respectivement.
- Mettez à jour les visites les plus récentes en ajoutant un lien "Afficher" pour les visites avec un fichier importé correspondant, ou "aucune" dans le cas contraire.
AVANT :
<!doctype html>
<html>
<head>
<title>VisitMe Example</title>
<body>
<h1>VisitMe example</h1>
<h3>Last 10 visits</h3>
<ul>
{% for visit in visits %}
<li>{{ visit.timestamp.ctime }} from {{ visit.visitor }}</li>
{% endfor %}
</ul>
</body>
</html>
Appliquez les modifications de la liste ci-dessus pour créer le modèle mis à jour :
APRÈS :
<!doctype html>
<html>
<head>
<title>VisitMe Example</title>
<body>
<h1>VisitMe example</h1>
{% if upload_url %}
<h3>Welcome... upload a file? (optional)</h3>
<form action="{{ upload_url }}" method="POST" enctype="multipart/form-data">
<input type="file" name="file"><p></p>
<input type="submit"> <input type="submit" value="Skip">
</form>
{% else %}
<h3>Last 10 visits</h3>
<ul>
{% for visit in visits %}
<li>{{ visit.timestamp.ctime() }}
<i><code>
{% if visit.file_blob %}
(<a href="/view/{{ visit.file_blob }}" target="_blank">view</a>)
{% else %}
(none)
{% endif %}
</code></i>
from {{ visit.visitor }}
</li>
{% endfor %}
</ul>
{% endif %}
</body>
</html>
Cette image illustre les mises à jour requises pour index.html :

Une dernière modification à apporter : Jinja2 préfère que ses modèles se trouvent dans un dossier templates. Créez donc ce dossier et déplacez-y index.html. Cette dernière étape vous permet d'apporter toutes les modifications nécessaires pour ajouter l'utilisation de Blobstore à l'exemple d'application du module 0.
(facultatif) "Amélioration" de Cloud Storage
Le stockage Blobstore a fini par évoluer pour devenir Cloud Storage. Cela signifie que les importations Blobstore sont visibles dans la console Cloud, plus précisément dans le navigateur Cloud Storage. La question est de savoir où. La réponse est le bucket Cloud Storage par défaut de votre application App Engine. Son nom correspond au nom de domaine complet de votre application App Engine, PROJECT_ID.appspot.com. C'est très pratique, car tous les ID de projet sont uniques, n'est-ce pas ?
Les mises à jour apportées à l'application exemple déposent les fichiers importés dans ce bucket, mais les développeurs ont la possibilité de choisir un emplacement plus spécifique. Le bucket par défaut est accessible par programmation via google.appengine.api.app_identity.get_default_gcs_bucket_name(). Vous devez donc effectuer une nouvelle importation si vous souhaitez accéder à cette valeur, par exemple pour l'utiliser comme préfixe pour organiser les fichiers importés. Par exemple, trier par type de fichier :

Pour implémenter une fonctionnalité similaire pour les images, par exemple, vous aurez un code comme celui-ci, ainsi qu'un code qui vérifie les types de fichiers pour choisir le nom de bucket souhaité :
ROOT_BUCKET = app_identity.get_default_gcs_bucket_name()
IMAGE_BUCKET = '%s/%s' % (ROOT_BUCKET, 'images')
Vous validerez également les images importées à l'aide d'un outil tel que le module imghdr de la bibliothèque standard Python pour confirmer le type d'image. Enfin, vous souhaiterez probablement limiter la taille des importations en cas de personnes malveillantes.
Imaginons que tout cela ait été fait. Comment mettre à jour notre application pour qu'elle permette de spécifier où stocker les fichiers importés ? La clé consiste à modifier l'appel à blobstore.create_upload_url dans MainHandler.get pour spécifier l'emplacement souhaité dans Cloud Storage pour l'importation en ajoutant le paramètre gs_bucket_name comme suit :
blobstore.create_upload_url('/upload', gs_bucket_name=IMAGE_BUCKET))
Comme il s'agit d'une mise à jour facultative si vous souhaitez spécifier où les importations doivent être effectuées, elle ne fait pas partie du fichier main.py dans le dépôt. En revanche, une alternative nommée main-gcs.py est disponible dans le dépôt. Au lieu d'utiliser un "dossier" de bucket distinct, le code de main-gcs.py stocke les importations dans le bucket "racine" (PROJECT_ID.appspot.com) comme main.py, mais fournit la structure dont vous avez besoin si vous deviez dériver l'échantillon en quelque chose de plus, comme indiqué dans cette section. Vous trouverez ci-dessous une illustration des différences entre main.py et main-gcs.py.

6. Résumé/Nettoyage
Cette section conclut cet atelier de programmation en déployant l'application et en vérifiant qu'elle fonctionne comme prévu et dans toutes les sorties reflétées. Après la validation de l'application, effectuez les étapes de nettoyage et réfléchissez aux prochaines étapes.
Déployer et vérifier l'application
Redéployez votre application avec gcloud app deploy et vérifiez qu'elle fonctionne comme prévu, avec une expérience utilisateur (UX) différente de celle de l'application du module 0. Votre application comporte désormais deux écrans différents, le premier étant l'invite du formulaire d'importation de fichiers de visite :
À partir de là, les utilisateurs finaux peuvent importer un fichier et cliquer sur "Envoyer", ou cliquer sur "Ignorer" pour ne rien importer. Dans les deux cas, le résultat est l'écran de visite le plus récent, désormais enrichi de liens "Afficher" ou de la mention "Aucun" entre les codes temporels de visite et les informations sur les visiteurs :

Bravo ! Vous avez terminé cet atelier de programmation et ajouté l'utilisation d'App Engine Blobstore à l'application exemple du module 0. Votre code doit maintenant correspondre à celui du dossier FINISH (Module 15). L'autre fichier main-gcs.py est également présent dans ce dossier.
Effectuer un nettoyage
Général
Si vous avez terminé pour le moment, nous vous recommandons de désactiver votre application App Engine pour éviter d'être facturé. Toutefois, si vous souhaitez effectuer d'autres tests ou expériences, la plate-forme App Engine dispose d'un quota sans frais. Tant que vous ne dépassez pas ce niveau d'utilisation, aucun frais ne devrait vous être facturé. Cela concerne le calcul, mais des frais peuvent également s'appliquer aux services App Engine concernés. Pour en savoir plus, consultez la page de tarification. Si cette migration implique d'autres services Cloud, ceux-ci sont facturés séparément. Dans les deux cas, le cas échéant, consultez la section "Spécifique à cet atelier de programmation" ci-dessous.
Pour être tout à fait transparent, le déploiement sur une plate-forme de calcul sans serveur Google Cloud comme App Engine entraîne de légers coûts de compilation et de stockage. Cloud Build et Cloud Storage disposent chacun de leur propre quota sans frais. Le stockage de cette image utilise une partie de ce quota. Toutefois, il est possible que vous résidiez dans une région où ce niveau sans frais n'est pas disponible. Veillez donc à surveiller votre utilisation de l'espace de stockage pour minimiser les coûts potentiels. Voici quelques "dossiers" Cloud Storage spécifiques que vous devez examiner :
console.cloud.google.com/storage/browser/LOC.artifacts.PROJECT_ID.appspot.com/containers/imagesconsole.cloud.google.com/storage/browser/staging.PROJECT_ID.appspot.com- Les liens de stockage ci-dessus dépendent de votre
PROJECT_IDet de votre *LOC*ation. Par exemple, "us" si votre application est hébergée aux États-Unis.
En revanche, si vous ne souhaitez pas poursuivre avec cette application ni avec d'autres ateliers de programmation de migration associés et que vous souhaitez tout supprimer complètement, arrêtez votre projet.
Spécifique à cet atelier de programmation
Les services listés ci-dessous sont propres à cet atelier de programmation. Pour en savoir plus, consultez la documentation de chaque produit :
- Le service Blobstore d'App Engine relève des quotas et limites de données stockées. Consultez également la page des tarifs des anciens services groupés.
- Le service App Engine Datastore est fourni par Cloud Datastore (Cloud Firestore en mode Datastore), qui propose également un niveau sans frais. Pour en savoir plus, consultez sa page de tarification.
Étapes suivantes
La prochaine migration logique à envisager est abordée dans le module 16, qui explique aux développeurs comment migrer du service Blobstore d'App Engine vers l'utilisation de la bibliothèque cliente Cloud Storage. La mise à niveau vous permet d'accéder à davantage de fonctionnalités Cloud Storage et de vous familiariser avec une bibliothèque cliente qui fonctionne pour les applications en dehors d'App Engine, que ce soit dans Google Cloud, dans d'autres clouds ou même sur site. Si vous n'avez pas besoin de toutes les fonctionnalités disponibles dans Cloud Storage ou si vous vous inquiétez de leur impact sur les coûts, vous pouvez continuer à utiliser App Engine Blobstore.
Au-delà du module 16, de nombreuses autres migrations sont possibles, comme Cloud NDB et Cloud Datastore, Cloud Tasks ou Cloud Memorystore. Il existe également des migrations interproduits vers Cloud Run et Cloud Functions. Le dépôt de migration contient tous les exemples de code, vous redirige vers tous les ateliers de programmation et toutes les vidéos disponibles, et vous indique également les migrations à envisager et l'ordre de migration à suivre.
7. Ressources supplémentaires
Problèmes/commentaires concernant l'atelier de programmation
Si vous rencontrez des problèmes avec cet atelier de programmation, commencez par faire une recherche avant de les signaler. Liens vers la recherche et la création d'un signalement :
Ressources de migration
Le tableau ci-dessous contient des liens vers les dossiers du dépôt pour les modules 0 (START) et 15 (FINISH). Vous pouvez également y accéder depuis le dépôt pour toutes les migrations d'ateliers de programmation App Engine que vous pouvez cloner ou télécharger sous forme de fichier ZIP.
Atelier de programmation | Python 2 | Python 3 |
Module 0 | N/A | |
Module 15 (cet atelier de programmation) | N/A |
Ressources en ligne
Vous trouverez ci-dessous des ressources en ligne qui peuvent être utiles pour ce tutoriel :
App Engine
- Service Blobstore App Engine
- Quotas et limites des données stockées dans App Engine
- Documentation App Engine
- Environnement d'exécution Python 2 App Engine (environnement standard)
- Utiliser les bibliothèques intégrées d'App Engine sur Python 2 App Engine
- Informations sur les tarifs et les quotas d'App Engine
- Lancement de la plate-forme App Engine de deuxième génération (2018)
- Comparer les plates-formes de première et de deuxième génération
- Compatibilité à long terme avec les anciens environnements d'exécution
- Dépôt d'exemples de migration de la documentation
- Dépôt d'exemples de migration issus de la communauté
Google Cloud
- Python sur Google Cloud Platform
- Bibliothèques clientes Google Cloud Python
- Niveau "Toujours sans frais" de Google Cloud
- SDK Google Cloud (outil de ligne de commande gcloud)
- Toute la documentation Google Cloud
Python
- Systèmes de création de modèles Django et Jinja2
webapp2framework Web- Documentation sur
webapp2 - Liens
webapp2_extras - Documentation
webapp2_extrasJinja2
Vidéos
- Serverless Migration Station
- Expéditions sans serveur
- S'abonner à Google Cloud Tech
- S'abonner à Google Developers
Licence
Ce document est publié sous une licence Creative Commons Attribution 2.0 Generic.