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.
- Teil 1:Richten Sie eine lokale Entwicklungsumgebung ein und stellen Sie dann sowohl eine Staging- als auch eine Produktionsumgebung auf Heroku bereit.
- Teil Zwei:Richten Sie eine PostgreSQL-Datenbank zusammen mit SQLAlchemy und Alembic ein, um Migrationen zu handhaben. (aktuell )
- 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.
- Teil Vier:Implementieren Sie eine Redis-Aufgabenwarteschlange für die Textverarbeitung.
- 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.
- 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.
- Teil 7:Aktualisieren Sie das Front-End, um es benutzerfreundlicher zu machen.
- 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.
- 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
- 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 erstelltenDATABASE_URL
ein Umgebungsvariable. - 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.