Database
 sql >> Base de données >  >> RDS >> Database

Flask par exemple - Configuration de Postgres, SQLAlchemy et Alembic

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.

  1. 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.
  2. Deuxième partie :configurer une base de données PostgreSQL avec SQLAlchemy et Alembic pour gérer les migrations. (actuel )
  3. 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).
  4. Quatrième partie :Implémenter une file d'attente de tâches Redis pour gérer le traitement de texte.
  5. Cinquième partie :Configurer Angular sur le front-end pour interroger en continu le back-end pour voir si la demande est traitée.
  6. 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.
  7. Septième partie :Mettez à jour l'interface pour la rendre plus conviviale.
  8. 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 de psycopg2 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 le init ou migrate 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.

  1. 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
  2. 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 nouvelle DATABASE_URL variable d'environnement.
  3. 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.