Database
 sql >> Datenbank >  >> RDS >> Database

Flask by Example – Einrichten von Postgres, SQLAlchemy und Alembic

In diesem Teil werden wir eine Postgres-Datenbank einrichten, um die Ergebnisse unserer Wortzählungen zu speichern, sowie SQLAlchemy, einen objektrelationalen Mapper, und Alembic, um Datenbankmigrationen zu handhaben.

Kostenloser Bonus: Klicken Sie hier, um Zugang zu einem kostenlosen Flask + Python-Video-Tutorial zu erhalten, das Ihnen Schritt für Schritt zeigt, wie Sie eine Flask-Webanwendung erstellen.

Aktualisierungen:

  • 09.02.2020:Upgrade auf Python Version 3.8.1 sowie die neuesten Versionen von Psycopg2, Flask-SQLAlchemy und Flask-Migrate. Siehe unten für Details. Installieren und verwenden Sie Flask-Script explizit aufgrund der Änderung der internen Flask-Migrate-Schnittstelle.
  • 22.03.2016:Upgrade auf Python Version 3.5.1 sowie die neuesten Versionen von Psycopg2, Flask-SQLAlchemy und Flask-Migrate. Einzelheiten siehe unten.
  • 22.02.2015:Python 3-Unterstützung hinzugefügt.

Denken Sie daran:Wir bauen Folgendes:Eine Flask-App, die Worthäufigkeitspaare basierend auf dem Text einer bestimmten URL berechnet.

  1. Teil 1:Richten Sie eine lokale Entwicklungsumgebung ein und stellen Sie dann sowohl eine Staging- als auch eine Produktionsumgebung auf Heroku bereit.
  2. Teil Zwei:Richten Sie eine PostgreSQL-Datenbank zusammen mit SQLAlchemy und Alembic ein, um Migrationen zu handhaben. (aktuell )
  3. Teil Drei:Fügen Sie die Back-End-Logik hinzu, um die Wortzählungen von einer Webseite mithilfe der Bibliotheken Requests, BeautifulSoup und Natural Language Toolkit (NLTK) zu schaben und dann zu verarbeiten.
  4. Teil Vier:Implementieren Sie eine Redis-Aufgabenwarteschlange für die Textverarbeitung.
  5. Teil Fünf:Richten Sie Angular am Front-End ein, um das Back-End kontinuierlich abzufragen, um zu sehen, ob die Verarbeitung der Anfrage abgeschlossen ist.
  6. Teil Sechs:Auf den Staging-Server auf Heroku pushen – Redis einrichten und detailliert beschreiben, wie zwei Prozesse (Web und Worker) auf einem einzigen Dyno ausgeführt werden.
  7. Teil 7:Aktualisieren Sie das Front-End, um es benutzerfreundlicher zu machen.
  8. Teil Acht:Erstellen Sie eine benutzerdefinierte Angular-Direktive, um ein Häufigkeitsverteilungsdiagramm mit JavaScript und D3 anzuzeigen.

Benötigen Sie den Code? Holen Sie es aus dem Repo.


Installationsvoraussetzungen

In diesem Teil verwendete Werkzeuge:

  • PostgreSQL (11.6)
  • Psycopg2 (2.8.4) - ein Python-Adapter für Postgres
  • Flask-SQLAlchemy (2.4.1) – Flask-Erweiterung, die SQLAlchemy-Unterstützung bereitstellt
  • Flask-Migrate (2.5.2) – Erweiterung, die SQLAlchemy-Datenbankmigrationen über Alembic unterstützt

Installieren Sie zunächst Postgres auf Ihrem lokalen Computer, falls Sie es noch nicht haben. Da Heroku Postgres verwendet, ist es gut für uns, lokal auf derselben Datenbank zu entwickeln. Wenn Sie Postgres nicht installiert haben, ist Postgres.app eine einfache Möglichkeit, Mac OS X-Benutzer zum Laufen zu bringen. Weitere Informationen finden Sie auf der Download-Seite.

Nachdem Sie Postgres installiert und ausgeführt haben, erstellen Sie eine Datenbank mit dem Namen wordcount_dev als unsere lokale Entwicklungsdatenbank zu verwenden:

$ psql
# create database wordcount_dev;
CREATE DATABASE
# \q

Um unsere neu erstellte Datenbank innerhalb der Flask-App verwenden zu können, müssen wir einige Dinge installieren:

$ cd flask-by-example

cd ing in das Verzeichnis sollte die virtuelle Umgebung aktivieren und die Umgebungsvariablen setzen, die in der .env gefunden werden Datei über autoenv, die wir in Teil 1 eingerichtet haben.

$ python -m pip install psycopg2==2.8.4 Flask-SQLAlchemy===2.4.1 Flask-Migrate==2.5.2
$ python -m pip freeze > requirements.txt

Wenn Sie OS X verwenden und Probleme bei der Installation von psycopg2 haben, sehen Sie sich diesen Stack Overflow-Artikel an.

Möglicherweise müssen Sie psycopg2-binary installieren statt psycopg2 wenn Ihre Installation fehlschlägt.



Konfiguration aktualisieren

Fügen Sie SQLALCHEMY_DATABASE_URI hinzu Feld in die Config() Klasse in Ihrer config.py Datei, um Ihre App so einzurichten, dass sie die neu erstellte Datenbank in Entwicklung (lokal), Staging und Produktion verwendet:

import os

class Config(object):
    ...
    SQLALCHEMY_DATABASE_URI = os.environ['DATABASE_URL']

Ihre config.py Die Datei sollte nun so aussehen:

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

Wenn jetzt unsere Konfiguration in unsere App geladen wird, wird auch die entsprechende Datenbank damit verbunden.

Ähnlich wie wir im letzten Beitrag eine Umgebungsvariable hinzugefügt haben, werden wir eine DATABASE_URL hinzufügen Variable. Führen Sie dies im Terminal aus:

$ export DATABASE_URL="postgresql:///wordcount_dev"

Und fügen Sie dann diese Zeile in Ihre .env ein Datei.

In Ihrer app.py Datei importieren Sie SQLAlchemy und verbinden Sie sich mit der Datenbank:

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()


Datenmodell

Richten Sie ein Basismodell ein, indem Sie eine models.py hinzufügen Datei:

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)

Hier haben wir eine Tabelle erstellt, um die Ergebnisse der Wortzählungen zu speichern.

Wir importieren zuerst die Datenbankverbindung, die wir in unsere app.py erstellt haben -Datei sowie JSON aus den PostgreSQL-Dialekten von SQLAlchemy. JSON-Spalten sind relativ neu für Postgres und nicht in jeder von SQLAlchemy unterstützten Datenbank verfügbar, daher müssen wir sie speziell importieren.

Als nächstes haben wir ein Result() erstellt -Klasse und wies ihr den Tabellennamen results zu . Dann legen wir die Attribute fest, die wir für ein Ergebnis speichern möchten-

  • die id des von uns gespeicherten Ergebnisses
  • die url von denen wir die Wörter gezählt haben
  • eine vollständige Liste der Wörter, die wir gezählt haben
  • eine Liste von Wörtern, die wir gezählt haben, minus Stoppwörter (dazu später mehr)

Wir haben dann ein __init__() erstellt Methode, die ausgeführt wird, wenn wir zum ersten Mal ein neues Ergebnis erstellen, und schließlich ein __repr__() Methode, um das Objekt darzustellen, wenn wir danach fragen.



Lokale Migration

Wir werden Alembic verwenden, das Teil von Flask-Migrate ist, um Datenbankmigrationen zu verwalten und das Schema einer Datenbank zu aktualisieren.

Hinweis: Flask-Migrate nutzt das neue CLI-Tool von Flask. Dieser Artikel verwendet jedoch die von Flask-Script bereitgestellte Schnittstelle, die zuvor von Flask-Migrate verwendet wurde. Um es zu verwenden, müssen Sie es installieren über:

$ python -m pip install Flask-Script==2.0.6
$ python -m pip freeze > requirements.txt

Erstellen Sie eine neue Datei namens 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()

Um Flask-Migrate zu verwenden, haben wir Manager importiert sowie Migrate und MigrateCommand zu unserer manage.py Datei. Wir haben auch app importiert und db Wir haben also vom Skript aus Zugriff darauf.

Zuerst stellen wir unsere Konfiguration so ein, dass unsere Umgebung – basierend auf der Umgebungsvariable – eine Migrationsinstanz mit app erstellt und db als Argumente und richten Sie einen manager ein Befehl zum Initialisieren eines Manager Beispiel für unsere App. Schließlich haben wir die db hinzugefügt Befehl an den manager damit wir die Migrationen über die Befehlszeile ausführen können.

Um die Migrationen auszuführen, initialisieren Sie 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.

Nachdem Sie die Datenbankinitialisierung ausgeführt haben, sehen Sie im Projekt einen neuen Ordner mit dem Namen „Migrations“. Dies enthält das Setup, das Alembic benötigt, um Migrationen für das Projekt auszuführen. Innerhalb von „Migrations“ sehen Sie, dass es einen Ordner namens „Versions“ gibt, der die Migrationsskripte enthält, sobald sie erstellt werden.

Lassen Sie uns unsere erste Migration erstellen, indem Sie migrate ausführen Befehl.

$ 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

Jetzt werden Sie feststellen, dass sich in Ihrem Ordner „Versionen“ eine Migrationsdatei befindet. Diese Datei wird von Alembic basierend auf dem Modell automatisch generiert. Sie könnten diese Datei selbst erstellen (oder bearbeiten); In den meisten Fällen reicht jedoch die automatisch generierte Datei aus.

Jetzt wenden wir die Upgrades mit db upgrade auf die Datenbank an Befehl:

$ 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

Die Datenbank ist jetzt bereit für uns, sie in unserer App zu verwenden:

$ 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)


Remote-Migration

Wenden wir abschließend die Migrationen auf die Datenbanken auf Heroku an. Zuerst müssen wir jedoch die Details der Staging- und Produktionsdatenbanken zur config.py hinzufügen Datei.

Um zu überprüfen, ob wir eine Datenbank auf dem Staging-Server eingerichtet haben, führen Sie Folgendes aus:

$ heroku config --app wordcount-stage
=== wordcount-stage Config Vars
APP_SETTINGS: config.StagingConfig

Stellen Sie sicher, dass Sie wordcount-stage ersetzen mit dem Namen Ihrer Staging-App.

Da wir keine Datenbankumgebungsvariable sehen, müssen wir das Postgres-Addon zum Staging-Server hinzufügen. Führen Sie dazu den folgenden Befehl aus:

$ 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 ist die kostenlose Stufe des Heroku Postgres-Addons.

Wenn wir jetzt heroku config --app wordcount-stage ausführen Wieder sollten wir die Verbindungseinstellungen für die Datenbank sehen:

=== 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

Als Nächstes müssen wir die Änderungen, die Sie an Git vorgenommen haben, festschreiben und auf Ihren Staging-Server übertragen:

$ git push stage master

Führen Sie die Migrationen aus, die wir erstellt haben, um unsere Staging-Datenbank zu migrieren, indem Sie heroku run verwenden Befehl:

$ 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

Beachten Sie, dass wir nur das upgrade ausgeführt haben , nicht die init oder migrate Befehle wie zuvor. Wir haben unsere Migrationsdatei bereits eingerichtet und können loslegen; wir müssen es nur auf die Heroku-Datenbank anwenden.

Machen wir jetzt dasselbe für die Produktion.

  1. Richten Sie eine Datenbank für Ihre Produktions-App auf Heroku ein, genau wie Sie es für das Staging getan haben:heroku addons:create heroku-postgresql:hobby-dev --app wordcount-pro
  2. Pushe deine Änderungen auf deine Produktionsseite:git push pro master Beachten Sie, dass Sie keine Änderungen an der Konfigurationsdatei vornehmen müssen – sie richtet die Datenbank basierend auf der neu erstellten DATABASE_URL ein Umgebungsvariable.
  3. Wenden Sie die Migrationen an:heroku run python manage.py db upgrade --app wordcount-pro

Jetzt haben sowohl unsere Staging- als auch unsere Produktionsstandorte ihre Datenbanken eingerichtet und migriert - und sind startklar!

Wenn Sie eine neue Migration auf die Produktionsdatenbank anwenden, kann es zu Ausfallzeiten kommen. Wenn dies ein Problem darstellt, können Sie die Datenbankreplikation einrichten, indem Sie eine „Follower“-Datenbank (allgemein bekannt als Slave-Datenbank) hinzufügen. Weitere Informationen hierzu finden Sie in der offiziellen Heroku-Dokumentation.



Schlussfolgerung

Das war es für Teil 2. Wenn Sie mehr über Flask erfahren möchten, sehen Sie sich unsere begleitende Videoserie an:

Kostenloser Bonus: Klicken Sie hier, um Zugang zu einem kostenlosen Flask + Python-Video-Tutorial zu erhalten, das Ihnen Schritt für Schritt zeigt, wie Sie eine Flask-Webanwendung erstellen.

In Teil 3 werden wir die Wortzählfunktion erstellen und sie an eine Aufgabenwarteschlange senden lassen, um die länger andauernde Wortzählverarbeitung zu bewältigen.

Bis zum nächsten Mal. Prost!

Dies ist eine Zusammenarbeit zwischen Cam Linke, Mitbegründer von Startup Edmonton, und den Leuten von Real Python.