Dans cette partie, nous allons configurer une base de données Postgres pour stocker les résultats de nos décomptes de mots ainsi que SQLAlchemy, un mappeur relationnel d'objet et Alembic pour gérer les migrations de base de données.
Bonus gratuit : Cliquez ici pour accéder à un didacticiel vidéo Flask + Python gratuit qui vous montre comment créer une application Web Flask, étape par étape.
Mises à jour :
- 09/02/2020 :mise à niveau vers Python version 3.8.1 ainsi que vers les dernières versions de Psycopg2, Flask-SQLAlchemy et Flask-Migrate. Voir ci-dessous pour plus de détails. Installez et utilisez explicitement Flask-Script en raison du changement de l'interface interne de Flask-Migrate.
- 22/03/2016 :Mise à jour vers Python version 3.5.1 ainsi que vers les dernières versions de Psycopg2, Flask-SQLAlchemy et Flask-Migrate. Voir ci-dessous pour plus de détails.
- 22/02/2015 :Ajout de la prise en charge de Python 3.
N'oubliez pas :voici ce que nous construisons - Une application Flask qui calcule les paires mot-fréquence en fonction du texte d'une URL donnée.
- Première partie :Configurez un environnement de développement local, puis déployez un environnement de préproduction et un environnement de production sur Heroku.
- Deuxième partie :configurer une base de données PostgreSQL avec SQLAlchemy et Alembic pour gérer les migrations. (actuel )
- Troisième partie :ajouter la logique back-end pour récupérer puis traiter le nombre de mots d'une page Web à l'aide des requêtes, de BeautifulSoup et des bibliothèques Natural Language Toolkit (NLTK).
- Quatrième partie :Implémenter une file d'attente de tâches Redis pour gérer le traitement de texte.
- Cinquième partie :Configurer Angular sur le front-end pour interroger en continu le back-end pour voir si la demande est traitée.
- Sixième partie :Transférez vers le serveur de préproduction sur Heroku :configurez Redis et expliquez comment exécuter deux processus (Web et Worker) sur un seul Dyno.
- Septième partie :Mettez à jour l'interface pour la rendre plus conviviale.
- Huitième partie :Créer une directive angulaire personnalisée pour afficher un tableau de distribution des fréquences à l'aide de JavaScript et de D3.
Besoin du code ? Récupérez-le dans le dépôt.
Configuration requise pour l'installation
Outils utilisés dans cette partie :
- PostgreSQL (11.6)
- Psycopg2 (2.8.4) - un adaptateur Python pour Postgres
- Flask-SQLAlchemy (2.4.1) - Extension Flask qui fournit la prise en charge de SQLAlchemy
- Flask-Migrate (2.5.2) - extension qui prend en charge les migrations de bases de données SQLAlchemy via Alembic
Pour commencer, installez Postgres sur votre ordinateur local, si vous ne l'avez pas déjà. Puisque Heroku utilise Postgres, il sera bon pour nous de développer localement sur la même base de données. Si vous n'avez pas installé Postgres, Postgres.app est un moyen simple d'être opérationnel pour les utilisateurs de Mac OS X. Consultez la page de téléchargement pour plus d'informations.
Une fois que vous avez installé et exécuté Postgres, créez une base de données appelée wordcount_dev
à utiliser comme base de données de développement local :
$ psql
# create database wordcount_dev;
CREATE DATABASE
# \q
Afin d'utiliser notre nouvelle base de données dans l'application Flask, nous devons installer quelques éléments :
$ cd flask-by-example
cd
entrer dans le répertoire doit activer l'environnement virtuel et définir les variables d'environnement trouvées dans le.env
fichier via autoenv, que nous avons configuré dans la partie 1.
$ python -m pip install psycopg2==2.8.4 Flask-SQLAlchemy===2.4.1 Flask-Migrate==2.5.2
$ python -m pip freeze > requirements.txt
Si vous êtes sous OS X et que vous rencontrez des difficultés pour installer psycopg2, consultez cet article Stack Overflow.
Vous devrez peut-être installer
psycopg2-binary
au lieu depsycopg2
si votre installation échoue.
Mettre à jour la configuration
Ajouter SQLALCHEMY_DATABASE_URI
champ au Config()
classe dans votre config.py pour configurer votre application afin qu'elle utilise la base de données nouvellement créée en développement (local), en préproduction et en production :
import os
class Config(object):
...
SQLALCHEMY_DATABASE_URI = os.environ['DATABASE_URL']
Votre config.py le fichier devrait maintenant ressembler à ceci :
import os
basedir = os.path.abspath(os.path.dirname(__file__))
class Config(object):
DEBUG = False
TESTING = False
CSRF_ENABLED = True
SECRET_KEY = 'this-really-needs-to-be-changed'
SQLALCHEMY_DATABASE_URI = os.environ['DATABASE_URL']
class ProductionConfig(Config):
DEBUG = False
class StagingConfig(Config):
DEVELOPMENT = True
DEBUG = True
class DevelopmentConfig(Config):
DEVELOPMENT = True
DEBUG = True
class TestingConfig(Config):
TESTING = True
Désormais, lorsque notre configuration sera chargée dans notre application, la base de données appropriée y sera également connectée.
Semblable à la façon dont nous avons ajouté une variable d'environnement dans le dernier message, nous allons ajouter un DATABASE_URL
variable. Exécutez ceci dans le terminal :
$ export DATABASE_URL="postgresql:///wordcount_dev"
Et puis ajoutez cette ligne dans votre .env fichier.
Dans votre app.py importez le fichier SQLAlchemy et connectez-vous à la base de données :
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
import os
app = Flask(__name__)
app.config.from_object(os.environ['APP_SETTINGS'])
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
db = SQLAlchemy(app)
from models import Result
@app.route('/')
def hello():
return "Hello World!"
@app.route('/<name>')
def hello_name(name):
return "Hello {}!".format(name)
if __name__ == '__main__':
app.run()
Modèle de données
Configurez un modèle de base en ajoutant un models.py fichier :
from app import db
from sqlalchemy.dialects.postgresql import JSON
class Result(db.Model):
__tablename__ = 'results'
id = db.Column(db.Integer, primary_key=True)
url = db.Column(db.String())
result_all = db.Column(JSON)
result_no_stop_words = db.Column(JSON)
def __init__(self, url, result_all, result_no_stop_words):
self.url = url
self.result_all = result_all
self.result_no_stop_words = result_no_stop_words
def __repr__(self):
return '<id {}>'.format(self.id)
Ici, nous avons créé une table pour stocker les résultats du nombre de mots.
Nous importons d'abord la connexion à la base de données que nous avons créée dans notre app.py ainsi que JSON des dialectes PostgreSQL de SQLAlchemy. Les colonnes JSON sont relativement nouvelles dans Postgres et ne sont pas disponibles dans toutes les bases de données prises en charge par SQLAlchemy, nous devons donc les importer spécifiquement.
Ensuite, nous avons créé un Result()
classe et lui a attribué un nom de table de results
. Nous définissons ensuite les attributs que nous voulons stocker pour un résultat-
- l'
id
du résultat que nous avons stocké - l'
url
dont nous avons compté les mots - une liste complète des mots que nous avons comptés
- une liste de mots que nous avons comptés moins les mots vides (plus à ce sujet plus tard)
Nous avons ensuite créé un __init__()
méthode qui s'exécutera la première fois que nous créerons un nouveau résultat et, enfin, un __repr__()
méthode pour représenter l'objet lorsque nous l'interrogeons.
Migration locale
Nous allons utiliser Alembic, qui fait partie de Flask-Migrate, pour gérer les migrations de bases de données afin de mettre à jour le schéma d'une base de données.
Remarque : Flask-Migrate utilise le nouvel outil CLI de Flasks. Cependant, cet article utilise l'interface fournie par Flask-Script, qui était utilisée auparavant par Flask-Migrate. Pour l'utiliser, vous devez l'installer via :
$ python -m pip install Flask-Script==2.0.6 $ python -m pip freeze > requirements.txt
Créez un nouveau fichier appelé manage.py :
import os
from flask_script import Manager
from flask_migrate import Migrate, MigrateCommand
from app import app, db
app.config.from_object(os.environ['APP_SETTINGS'])
migrate = Migrate(app, db)
manager = Manager(app)
manager.add_command('db', MigrateCommand)
if __name__ == '__main__':
manager.run()
Pour utiliser Flask-Migrate, nous avons importé Manager
ainsi que Migrate
et MigrateCommand
à notre manage.py dossier. Nous avons également importé app
et db
nous y avons donc accès depuis le script.
Tout d'abord, nous définissons notre configuration pour que notre environnement - basé sur la variable d'environnement - crée une instance de migration, avec app
et db
comme arguments, et configurez un manager
commande pour initialiser un Manager
exemple pour notre application. Enfin, nous avons ajouté le db
commande au manager
afin que nous puissions exécuter les migrations à partir de la ligne de commande.
Afin d'exécuter les migrations, initialisez Alembic :
$ python manage.py db init
Creating directory /flask-by-example/migrations ... done
Creating directory /flask-by-example/migrations/versions ... done
Generating /flask-by-example/migrations/alembic.ini ... done
Generating /flask-by-example/migrations/env.py ... done
Generating /flask-by-example/migrations/README ... done
Generating /flask-by-example/migrations/script.py.mako ... done
Please edit configuration/connection/logging settings in
'/flask-by-example/migrations/alembic.ini' before proceeding.
Après avoir exécuté l'initialisation de la base de données, vous verrez un nouveau dossier appelé "migrations" dans le projet. Cela contient la configuration nécessaire pour qu'Alembic exécute des migrations sur le projet. À l'intérieur de "migrations", vous verrez qu'il contient un dossier appelé "versions", qui contiendra les scripts de migration au fur et à mesure de leur création.
Créons notre première migration en exécutant le migrate
commande.
$ python manage.py db migrate
INFO [alembic.runtime.migration] Context impl PostgresqlImpl.
INFO [alembic.runtime.migration] Will assume transactional DDL.
INFO [alembic.autogenerate.compare] Detected added table 'results'
Generating /flask-by-example/migrations/versions/63dba2060f71_.py
... done
Vous remarquerez maintenant que dans votre dossier "versions", il y a un fichier de migration. Ce fichier est généré automatiquement par Alembic en fonction du modèle. Vous pouvez générer (ou modifier) ce fichier vous-même ; cependant, dans la plupart des cas, le fichier généré automatiquement fera l'affaire.
Nous allons maintenant appliquer les mises à niveau à la base de données à l'aide de la db upgrade
commande :
$ python manage.py db upgrade
INFO [alembic.runtime.migration] Context impl PostgresqlImpl.
INFO [alembic.runtime.migration] Will assume transactional DDL.
INFO [alembic.runtime.migration] Running upgrade -> 63dba2060f71, empty message
La base de données est maintenant prête à être utilisée dans notre application :
$ psql
# \c wordcount_dev
You are now connected to database "wordcount_dev" as user "michaelherman".
# \dt
List of relations
Schema | Name | Type | Owner
--------+-----------------+-------+---------------
public | alembic_version | table | michaelherman
public | results | table | michaelherman
(2 rows)
# \d results
Table "public.results"
Column | Type | Modifiers
----------------------+-------------------+------------------------------------------------------
id | integer | not null default nextval('results_id_seq'::regclass)
url | character varying |
result_all | json |
result_no_stop_words | json |
Indexes:
"results_pkey" PRIMARY KEY, btree (id)
Migration à distance
Enfin, appliquons les migrations aux bases de données sur Heroku. Cependant, nous devons d'abord ajouter les détails des bases de données intermédiaires et de production au config.py fichier.
Pour vérifier si une base de données est configurée sur le serveur intermédiaire, exécutez :
$ heroku config --app wordcount-stage
=== wordcount-stage Config Vars
APP_SETTINGS: config.StagingConfig
Assurez-vous de remplacer
wordcount-stage
avec le nom de votre application de staging.
Comme nous ne voyons pas de variable d'environnement de base de données, nous devons ajouter l'addon Postgres au serveur intermédiaire. Pour ce faire, exécutez la commande suivante :
$ heroku addons:create heroku-postgresql:hobby-dev --app wordcount-stage
Creating postgresql-cubic-86416... done, (free)
Adding postgresql-cubic-86416 to wordcount-stage... done
Setting DATABASE_URL and restarting wordcount-stage... done, v8
Database has been created and is available
! This database is empty. If upgrading, you can transfer
! data from another database with pg:copy
Use `heroku addons:docs heroku-postgresql` to view documentation.
hobby-dev
est le niveau gratuit de l'addon Heroku Postgres.
Maintenant, lorsque nous exécutons heroku config --app wordcount-stage
encore une fois, nous devrions voir les paramètres de connexion pour la base de données :
=== wordcount-stage Config Vars
APP_SETTINGS: config.StagingConfig
DATABASE_URL: postgres://azrqiefezenfrg:Zti5fjSyeyFgoc-U-yXnPrXHQv@ec2-54-225-151-64.compute-1.amazonaws.com:5432/d2kio2ubc804p7
Ensuite, nous devons valider les modifications que vous avez apportées à git et les envoyer à votre serveur intermédiaire :
$ git push stage master
Exécutez les migrations que nous avons créées pour migrer notre base de données intermédiaire en utilisant le heroku run
commande :
$ heroku run python manage.py db upgrade --app wordcount-stage
Running python manage.py db upgrade on wordcount-stage... up, run.5677
INFO [alembic.runtime.migration] Context impl PostgresqlImpl.
INFO [alembic.runtime.migration] Will assume transactional DDL.
INFO [alembic.runtime.migration] Running upgrade -> 63dba2060f71, empty message
Remarquez comment nous n'avons exécuté que la
upgrade
, pas leinit
oumigrate
commandes comme avant. Nous avons déjà notre fichier de migration configuré et prêt à partir ; nous avons juste besoin de l'appliquer à la base de données Heroku.
Faisons maintenant de même pour la production.
- Configurez une base de données pour votre application de production sur Heroku, comme vous l'avez fait pour la mise en scène :
heroku addons:create heroku-postgresql:hobby-dev --app wordcount-pro
- Poussez vos modifications sur votre site de production :
git push pro master
Remarquez que vous n'avez pas à apporter de modifications au fichier de configuration - il définit la base de données en fonction de la nouvelleDATABASE_URL
variable d'environnement. - Appliquez les migrations :
heroku run python manage.py db upgrade --app wordcount-pro
Maintenant, nos sites de préparation et de production ont leurs bases de données configurées et sont migrées - et prêtes à fonctionner !
Lorsque vous appliquez une nouvelle migration à la base de données de production, il peut y avoir un temps d'arrêt. Si cela pose problème, vous pouvez configurer la réplication de base de données en ajoutant une base de données « suiveuse » (communément appelée esclave). Pour en savoir plus, consultez la documentation officielle d'Heroku.
Conclusion
C'est tout pour la partie 2. Si vous souhaitez approfondir Flask, consultez notre série de vidéos d'accompagnement :
Bonus gratuit : Cliquez ici pour accéder à un didacticiel vidéo Flask + Python gratuit qui vous montre comment créer une application Web Flask, étape par étape.
Dans la partie 3, nous allons créer la fonctionnalité de comptage de mots et l'envoyer à une file d'attente de tâches pour gérer le traitement de comptage de mots plus long.
À la prochaine. Santé !
Il s'agit d'une collaboration entre Cam Linke, co-fondateur de Startup Edmonton, et les gens de Real Python.