:orphan: ====================== TD n°2 : Déploiement ====================== Dans ce TD, nous allons voir comment publier notre application Flask sur un service d'hébergement gratuit. Nous utiliserons https://www.pythonanywhere.com/. Création d'un compte ==================== * Rendez-vous sur https://www.pythonanywhere.com/ * En haut à droite, cliquez sur *Pricing & signup* * Cliquez sur *Create Beginner account* Chargement des fichiers ======================= * Compressez les fichiers de votre application dans un fichier ZIP * Depuis l'onglet *Files* de PythonAnywhere, créez un répertoire ``tp-ensembl``, et téléversez-y votre fichier ZIP * Cliquez ensuite sur *Open Bash console here* * Dans la console, décompressez votre archive avec la commande ``unzip VOTRE_FICHIER.zip`` * Téléversez ensuite `le fichier Sqlite`__ dans le même répertoire (cela va prendre un certain temps) __ ../_static/ensembl_hs63_simple.sqlite Création de l'application ========================= * Depuis l'onlget Web, cliquez sur *Add a new web app* * Sélectionnez Flask et Python 3.6 * Choisissez comme fichier un fichier *inexistant* dans le répertoire ``tp-ensembl``, par exemple ``/home/LOGIN/tp-ensembl/flask_app.py`` * Ouvrez l'application : elle affiche "Hello from Flask" * Depuis une console Bash, ouverte dans ``tp-ensembl``, supprimez ``flask_app.py`` et remplacez le par un lien symbolique (``ln -s``) vers votre propre fichier Python (ou renommez votre fichier Pyhon en ``flask_app.py``) * Depuis l'onglet Web, rechargez l'application * Ouvrez l'application : c'est la vôtre ! * Vérifiez que votre application fonctionne correctement * Testez l'application de votre voisin⋅e, Pour aller plus loin : MySQL ============================ La base de données Sqlite3 que nous utilisons est parfaite pour développer, mais pas pour un site en production. * Dans l'onglet *Files*, téléversez `ce fichier <../_static/ensembl_hs63_simple.sql>`_ à la racine de votre compte (cela peut prendre un certain temps) * Ouvrez l'onglet *Databases*, sous-onglet *MysSQL* * Choisissez un mot de passe pour la base de données (**différent** du mot de passe de votre compte) * Dans *Create database*, entrez le texte ``ensembl`` et cliquez sur *Create* * Ouvrez une console en cliquant sur le lient ``LOGIN$ensembl`` * Importez le contenu de la base Ensembl à l'aide de la commande ``source ensembl_hs63_simple.sql`` * L'import prend un certain temps, ignorez les erreurs * Vérifiez que tout s'est bien passé avec la requête ``select * from Genes limit 10;`` Nous pouvons maintenant modifier le fichier Python pour qu'il utilise la base de données MySQL ; il suffit normalement d'importer ``mysql.connector``, et de remplacer la chaîne de connexion à la base par : .. code-block:: python cx = mysql.connector.connect( user="LOGIN", password="MYSQL-PASSWD", host="LOGIN.mysql.pythonanywhere-services.com", database="LOGIN$ensembl" ) Bien sûr, il n'est pas très judicieux de laisser ces informations dans le code Python. On préfère en général les stocker dans un fichier séparé, et lire ce fichier depuis le code python. On peut même, dans ce fichier de configuration, autoriser deux types de configuration, Sqlite3 et MySQL, et améliorer le code Python pour qu'il utilise l'un ou l'autre système en fonction de la configuration. Ainsi, ce fichier sera le seul à différer entre votre environnement de développement (sur votre machine) et l'environnement de production (chez l'hébergeur). .. warning:: Compatibilité Sqlite3 / MySQL Les bibliothèques Sqlite3 et MySQL en Python sont globalement compatibles, car elles respectent le même standard `DbAPI2 <249>`:pep:. Cela étant dit, chacune propose ses propres extensions du standard, donc selon la manière de coder, votre programme peut nécessiter des adaptations pour fonctionner avec MySQL. Notamment, les fonctionalités suivantes de Sqlite3 ne sont pas standard : * exécution de requête directe depuis l'objet connexion : .. code-block:: python # n'écrivez pas c = cx.execute(query) # mais écrivez c = cx.cursor() c.execute(query) * résultat sous forme de dicionnaire : .. code-block:: python cx.row_factory = sqlite3.Row # pas supporté par MySQL Pour reproduire cette fonctionalité de manière standard, on peut par exemple passer par la fonction suivante : .. code-block:: python def fetchall_dict(c): """ Utilisez fetchall_dict(c) au lieu de c.fetchall() pour récupérer des dictionnaires au lieu de tuples. """ col_names = [ d[0] for d in c.description ] for row in c.fetchall(): yield dict(zip(col_names, row))