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

Flask per esempio:configurazione di Postgres, SQLAlchemy e Alembic

In questa parte imposteremo un database Postgres per memorizzare i risultati del nostro conteggio delle parole, nonché SQLAlchemy, un Object Relational Mapper e Alambic per gestire le migrazioni del database.

Bonus gratuito: Fai clic qui per accedere a un video tutorial gratuito di Flask + Python che ti mostra come creare l'app Web Flask, passo dopo passo.

Aggiornamenti:

  • 02/09/2020:aggiornato a Python versione 3.8.1 e alle ultime versioni di Psycopg2, Flask-SQLAlchemy e Flask-Migrate. Vedi sotto per i dettagli. Installa e usa in modo esplicito Flask-Script a causa della modifica dell'interfaccia interna di Flask-Migrate.
  • 22/03/2016:aggiornato a Python versione 3.5.1 e alle ultime versioni di Psycopg2, Flask-SQLAlchemy e Flask-Migrate. Vedi sotto per i dettagli.
  • 22/02/2015:Aggiunto supporto per Python 3.

Ricorda:ecco cosa stiamo costruendo:un'app Flask che calcola le coppie parola-frequenza in base al testo di un determinato URL.

  1. Parte uno:imposta un ambiente di sviluppo locale e quindi distribuisci sia un ambiente di staging che un ambiente di produzione su Heroku.
  2. Parte due:configurare un database PostgreSQL insieme a SQLAlchemy e Alembic per gestire le migrazioni. (attuale )
  3. Parte terza:aggiungi la logica di back-end per raschiare e quindi elaborare il conteggio delle parole da una pagina web utilizzando le librerie Request, BeautifulSoup e Natural Language Toolkit (NLTK).
  4. Parte quarta:implementare una coda di attività Redis per gestire l'elaborazione del testo.
  5. Parte cinque:imposta Angular sul front-end per eseguire continuamente il polling del back-end per vedere se l'elaborazione della richiesta è stata completata.
  6. Parte sei:push al server di staging su Heroku:configurazione di Redis e dettagli su come eseguire due processi (web e worker) su un singolo Dyno.
  7. Parte 7:aggiorna il front-end per renderlo più intuitivo.
  8. Parte otto:crea una direttiva angolare personalizzata per visualizzare un grafico di distribuzione della frequenza utilizzando JavaScript e D3.

Ti serve il codice? Prendilo dal repository.


Requisiti di installazione

Strumenti utilizzati in questa parte:

  • PostgreSQL (11.6)
  • Psycopg2 (2.8.4) - un adattatore Python per Postgres
  • Flask-SQLAlchemy (2.4.1) - Estensione Flask che fornisce supporto SQLAlchemy
  • Flask-Migrate (2.5.2) - estensione che supporta le migrazioni di database SQLAlchemy tramite Alembic

Per iniziare, installa Postgres sul tuo computer locale, se non lo hai già. Poiché Heroku utilizza Postgres, sarà utile per noi sviluppare localmente sullo stesso database. Se non hai installato Postgres, Postgres.app è un modo semplice per iniziare a funzionare per gli utenti di Mac OS X. Consulta la pagina di download per maggiori informazioni.

Dopo aver installato e avviato Postgres, crea un database chiamato wordcount_dev da utilizzare come nostro database di sviluppo locale:

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

Per utilizzare il nostro database appena creato all'interno dell'app Flask, dobbiamo installare alcune cose:

$ cd flask-by-example

cd ing nella directory dovrebbe attivare l'ambiente virtuale e impostare le variabili di ambiente che si trovano nel .env file tramite autoenv, che abbiamo impostato nella parte 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

Se utilizzi OS X e hai problemi con l'installazione di psycopg2, dai un'occhiata a questo articolo sull'overflow dello stack.

Potrebbe essere necessario installare psycopg2-binary invece di psycopg2 se l'installazione non riesce.



Aggiorna configurazione

Aggiungi SQLALCHEMY_DATABASE_URI campo nel Config() classe nel tuo config.py per impostare la tua app in modo che utilizzi il database appena creato in fase di sviluppo (locale), staging e produzione:

import os

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

Il tuo config.py il file ora dovrebbe assomigliare a questo:

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

Ora, quando la nostra configurazione viene caricata nella nostra app, anche il database appropriato verrà collegato ad essa.

Simile a come abbiamo aggiunto una variabile di ambiente nell'ultimo post, aggiungeremo un DATABASE_URL variabile. Esegui questo nel terminale:

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

E poi aggiungi quella riga nel tuo .env file.

Nel tuo app.py importare file SQLAlchemy e connettersi al database:

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


Modello di dati

Imposta un modello di base aggiungendo un models.py file:

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)

Qui abbiamo creato una tabella per memorizzare i risultati del conteggio delle parole.

Per prima cosa importiamo la connessione al database che abbiamo creato nel nostro app.py file e JSON dai dialetti PostgreSQL di SQLAlchemy. Le colonne JSON sono abbastanza nuove per Postgres e non sono disponibili in tutti i database supportati da SQLAlchemy, quindi è necessario importarle in modo specifico.

Successivamente abbiamo creato un Result() class e gli ha assegnato un nome di tabella di results . Quindi impostiamo gli attributi che vogliamo memorizzare per un risultato-

  • l'id del risultato che abbiamo memorizzato
  • l'url da cui abbiamo contato le parole
  • un elenco completo di parole che abbiamo contato
  • un elenco di parole che abbiamo contato meno le parole chiave (ne parleremo più avanti)

Abbiamo quindi creato un __init__() metodo che verrà eseguito la prima volta che creiamo un nuovo risultato e, infine, un __repr__() metodo per rappresentare l'oggetto quando lo interroghiamo.



Migrazione locale

Utilizzeremo Alembic, che fa parte di Flask-Migrate, per gestire le migrazioni di database per aggiornare lo schema di un database.

Nota: Flask-Migrate utilizza il nuovo strumento CLI di Flasks. Tuttavia, questo articolo utilizza l'interfaccia fornita da Flask-Script, utilizzata in precedenza da Flask-Migrate. Per usarlo, devi installarlo tramite:

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

Crea un nuovo file chiamato 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()

Per poter utilizzare Flask-Migrate abbiamo importato Manager così come Migrate e MigrateCommand al nostro manage.py file. Abbiamo anche importato app e db quindi abbiamo accesso ad essi dall'interno dello script.

Per prima cosa, impostiamo la nostra configurazione in modo che il nostro ambiente, basato sulla variabile di ambiente, crei un'istanza di migrazione, con app e db come argomenti e imposta un manager comando per inizializzare un Manager esempio per la nostra app. Infine, abbiamo aggiunto il db comando al manager in modo da poter eseguire le migrazioni dalla riga di comando.

Per eseguire le migrazioni inizializzare Alambic:

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

Dopo aver eseguito l'inizializzazione del database, vedrai una nuova cartella chiamata "migrazioni" nel progetto. Ciò mantiene la configurazione necessaria affinché Alembic esegua le migrazioni rispetto al progetto. All'interno di "migrazioni" vedrai che ha una cartella chiamata "versioni", che conterrà gli script di migrazione man mano che vengono creati.

Creiamo la nostra prima migrazione eseguendo migrate comando.

$ 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

Ora noterai che nella cartella "versioni" è presente un file di migrazione. Questo file viene generato automaticamente da Alambic in base al modello. Potresti generare (o modificare) questo file tu stesso; tuttavia, nella maggior parte dei casi, il file generato automaticamente funzionerà.

Ora applicheremo gli aggiornamenti al database utilizzando db upgrade comando:

$ 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

Il database è ora pronto per essere utilizzato nella nostra app:

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


Migrazione remota

Infine, applichiamo le migrazioni ai database su Heroku. Prima, però, dobbiamo aggiungere i dettagli dei database di staging e produzione a config.py file.

Per verificare se abbiamo un database impostato sul server di staging, esegui:

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

Assicurati di sostituire wordcount-stage con il nome della tua app di staging.

Dal momento che non vediamo una variabile di ambiente del database, dobbiamo aggiungere l'addon Postgres al server di staging. Per farlo, esegui il seguente comando:

$ 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 è il livello gratuito del componente aggiuntivo Heroku Postgres.

Ora, quando eseguiamo heroku config --app wordcount-stage di nuovo dovremmo vedere le impostazioni di connessione per il database:

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

Quindi dobbiamo eseguire il commit delle modifiche che hai apportato a git e inviarle al tuo server di staging:

$ git push stage master

Esegui le migrazioni che abbiamo creato per migrare il nostro database di staging utilizzando heroku run comando:

$ 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

Nota come abbiamo eseguito solo l'upgrade , non il init o migrate comandi come prima. Abbiamo già il nostro file di migrazione configurato e pronto per l'uso; dobbiamo solo applicarlo al database di Heroku.

Ora facciamo lo stesso per la produzione.

  1. Configura un database per la tua app di produzione su Heroku, proprio come hai fatto per lo staging:heroku addons:create heroku-postgresql:hobby-dev --app wordcount-pro
  2. Invia le modifiche al tuo sito di produzione:git push pro master Nota come non devi apportare modifiche al file di configurazione:sta impostando il database in base al DATABASE_URL appena creato variabile di ambiente.
  3. Applica le migrazioni:heroku run python manage.py db upgrade --app wordcount-pro

Ora sia i nostri siti di staging che quelli di produzione hanno i loro database configurati, migrati e pronti per l'uso!

Quando si applica una nuova migrazione al database di produzione, potrebbero verificarsi tempi di inattività. Se questo è un problema, puoi configurare la replica del database aggiungendo un database "follower" (comunemente noto come slave). Per ulteriori informazioni, consulta la documentazione ufficiale di Heroku.



Conclusione

Questo è tutto per la parte 2. Se desideri approfondire Flask, dai un'occhiata alla nostra serie di video di accompagnamento:

Bonus gratuito: Fai clic qui per accedere a un video tutorial gratuito di Flask + Python che ti mostra come creare l'app Web Flask, passo dopo passo.

Nella parte 3 creeremo la funzionalità di conteggio delle parole e la invieremo a una coda di attività per gestire l'elaborazione del conteggio delle parole più lunga.

Arrivederci alla prossima. Saluti!

Questo è un pezzo di collaborazione tra Cam Linke, co-fondatore di Startup Edmonton, e la gente di Real Python.