sql >> Base de Datos >  >> RDS >> Database

Frasco por ejemplo:configuración de Postgres, SQLAlchemy y Alembic

En esta parte, vamos a configurar una base de datos de Postgres para almacenar los resultados de nuestros conteos de palabras, así como SQLAlchemy, un mapeador relacional de objetos y Alambic para manejar las migraciones de la base de datos.

Bonificación gratuita: Haga clic aquí para obtener acceso a un videotutorial gratuito de Flask + Python que le muestra cómo crear la aplicación web de Flask, paso a paso.

Actualizaciones:

  • 09/02/2020:actualizado a la versión 3.8.1 de Python, así como a las últimas versiones de Psycopg2, Flask-SQLAlchemy y Flask-Migrate. Consulte a continuación para obtener más información. Instale y use explícitamente Flask-Script debido al cambio de la interfaz interna de Flask-Migrate.
  • 22/03/2016:actualizado a la versión 3.5.1 de Python, así como a las últimas versiones de Psycopg2, Flask-SQLAlchemy y Flask-Migrate. Vea a continuación para obtener más detalles.
  • 22/02/2015:Se agregó compatibilidad con Python 3.

Recuerda:esto es lo que estamos creando:una aplicación Flask que calcula pares de palabras y frecuencias en función del texto de una URL determinada.

  1. Primera parte:configure un entorno de desarrollo local y luego implemente un entorno de ensayo y uno de producción en Heroku.
  2. Segunda parte:configure una base de datos PostgreSQL junto con SQLAlchemy y Alambic para manejar las migraciones. (actual )
  3. Tercera parte:agregue la lógica de back-end para raspar y luego procesar los recuentos de palabras de una página web utilizando las bibliotecas de solicitudes, BeautifulSoup y Natural Language Toolkit (NLTK).
  4. Cuarta parte:implementar una cola de tareas de Redis para manejar el procesamiento de texto.
  5. Quinta parte:Configure Angular en el front-end para sondear continuamente el back-end para ver si la solicitud ha terminado de procesarse.
  6. Sexta parte:enviar al servidor de prueba en Heroku:configurar Redis y detallar cómo ejecutar dos procesos (web y trabajador) en un solo Dyno.
  7. Séptima parte:actualice la interfaz para que sea más fácil de usar.
  8. Octava parte:Cree una directiva angular personalizada para mostrar un gráfico de distribución de frecuencia usando JavaScript y D3.

¿Necesitas el código? Cógelo del repositorio.


Requisitos de instalación

Herramientas utilizadas en esta parte:

  • PostgreSQL (11.6)
  • Psycopg2 (2.8.4):un adaptador de Python para Postgres
  • Flask-SQLAlchemy (2.4.1):extensión de Flask que proporciona compatibilidad con SQLAlchemy
  • Flask-Migrate (2.5.2):extensión que admite migraciones de bases de datos SQLAlchemy a través de Alembic

Para comenzar, instale Postgres en su computadora local, si aún no lo tiene. Dado que Heroku usa Postgres, será bueno para nosotros desarrollar localmente en la misma base de datos. Si no tiene Postgres instalado, Postgres.app es una manera fácil de ponerlo en marcha para los usuarios de Mac OS X. Consulte la página de descarga para obtener más información.

Una vez que haya instalado y ejecutado Postgres, cree una base de datos llamada wordcount_dev para usar como nuestra base de datos de desarrollo local:

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

Para utilizar nuestra base de datos recién creada dentro de la aplicación Flask, debemos instalar algunas cosas:

$ cd flask-by-example

cd Entrar en el directorio debería activar el entorno virtual y establecer las variables de entorno que se encuentran en .env archivo a través de autoenv, que configuramos en la 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

Si tiene OS X y tiene problemas para instalar psycopg2, consulte este artículo sobre desbordamiento de pila.

Es posible que deba instalar psycopg2-binary en lugar de psycopg2 si su instalación falla.



Actualizar configuración

Agregue SQLALCHEMY_DATABASE_URI campo a Config() clase en su config.py archivo para configurar su aplicación para usar la base de datos recién creada en desarrollo (local), preparación y producción:

import os

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

Su config.py El archivo ahora debería verse así:

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

Ahora, cuando nuestra configuración se cargue en nuestra aplicación, la base de datos adecuada también se conectará a ella.

Similar a cómo agregamos una variable de entorno en la última publicación, vamos a agregar un DATABASE_URL variable. Ejecute esto en la terminal:

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

Y luego agregue esa línea en su .env archivo.

En tu app.py importar archivo SQLAlchemy y conectarse a la base de datos:

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


Modelo de datos

Configure un modelo básico agregando un models.py archivo:

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)

Aquí creamos una tabla para almacenar los resultados de los conteos de palabras.

Primero importamos la conexión de base de datos que creamos en nuestro app.py archivo, así como JSON de los dialectos PostgreSQL de SQLAlchemy. Las columnas JSON son bastante nuevas para Postgres y no están disponibles en todas las bases de datos compatibles con SQLAlchemy, por lo que debemos importarlas específicamente.

Luego creamos un Result() clase y le asignó un nombre de tabla de results . Luego establecemos los atributos que queremos almacenar para un resultado-

  • el id del resultado que almacenamos
  • la url que contamos las palabras de
  • una lista completa de palabras que contamos
  • una lista de palabras que contamos menos palabras vacías (más sobre esto más adelante)

Luego creamos un __init__() método que se ejecutará la primera vez que creamos un nuevo resultado y, finalmente, un __repr__() para representar el objeto cuando lo consultamos.



Migración local

Vamos a usar Alembic, que es parte de Flask-Migrate, para administrar las migraciones de bases de datos para actualizar el esquema de una base de datos.

Nota: Flask-Migrate utiliza la nueva herramienta CLI de Flasks. Sin embargo, este artículo usa la interfaz provista por Flask-Script, que Flask-Migrate usó antes. Para usarlo, debe instalarlo a través de:

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

Cree un nuevo archivo llamado 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()

Para usar Flask-Migrate importamos Manager así como Migrate y MigrateCommand a nuestro manage.py expediente. También importamos app y db por lo que tenemos acceso a ellos desde el script.

Primero, configuramos nuestra configuración para que nuestro entorno, basado en la variable de entorno, cree una instancia de migración, con app y db como argumentos y configurar un manager comando para inicializar un Manager instancia para nuestra aplicación. Finalmente, agregamos el db comando al manager para que podamos ejecutar las migraciones desde la línea de comandos.

Para ejecutar las migraciones, inicialice 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.

Después de ejecutar la inicialización de la base de datos, verá una nueva carpeta llamada "migraciones" en el proyecto. Esto contiene la configuración necesaria para que Alambic ejecute migraciones contra el proyecto. Dentro de "migraciones" verá que tiene una carpeta llamada "versiones", que contendrá los scripts de migración a medida que se crean.

Vamos a crear nuestra primera migración ejecutando 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

Ahora notará que en su carpeta de "versiones" hay un archivo de migración. Este archivo es generado automáticamente por Alembic basado en el modelo. Puede generar (o editar) este archivo usted mismo; sin embargo, en la mayoría de los casos, el archivo generado automáticamente servirá.

Ahora aplicaremos las actualizaciones a la base de datos usando 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

La base de datos ya está lista para que la usemos en nuestra aplicación:

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


Migración remota

Finalmente, apliquemos las migraciones a las bases de datos en Heroku. Sin embargo, primero debemos agregar los detalles de las bases de datos de preparación y producción a config.py archivo.

Para verificar si tenemos una base de datos configurada en el servidor de ensayo, ejecute:

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

Asegúrate de reemplazar wordcount-stage con el nombre de su aplicación de prueba.

Como no vemos una variable de entorno de base de datos, debemos agregar el complemento de Postgres al servidor de ensayo. Para hacerlo, ejecute el siguiente 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 es el nivel gratuito del complemento Heroku Postgres.

Ahora, cuando ejecutamos heroku config --app wordcount-stage nuevamente deberíamos ver la configuración de conexión para la base de datos:

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

A continuación, debemos confirmar los cambios que ha realizado en git y enviarlos a su servidor de ensayo:

$ git push stage master

Ejecute las migraciones que creamos para migrar nuestra base de datos provisional mediante 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

Observe cómo solo ejecutamos la upgrade , no el init o migrate comandos como antes. Ya tenemos nuestro archivo de migración configurado y listo para funcionar; solo necesitamos aplicarlo en la base de datos de Heroku.

Ahora hagamos lo mismo para la producción.

  1. Configure una base de datos para su aplicación de producción en Heroku, tal como lo hizo para la puesta en escena:heroku addons:create heroku-postgresql:hobby-dev --app wordcount-pro
  2. Envíe sus cambios a su sitio de producción:git push pro master Observe cómo no tiene que hacer ningún cambio en el archivo de configuración:está configurando la base de datos en función del DATABASE_URL recién creado variable de entorno.
  3. Aplicar las migraciones:heroku run python manage.py db upgrade --app wordcount-pro

Ahora, tanto nuestros sitios de preparación como de producción tienen sus bases de datos configuradas y migradas, ¡y listas para funcionar!

Cuando aplica una nueva migración a la base de datos de producción, puede haber tiempo de inactividad. Si esto es un problema, puede configurar la replicación de la base de datos agregando una base de datos "seguidora" (comúnmente conocida como esclava). Para obtener más información al respecto, consulte la documentación oficial de Heroku.



Conclusión

Eso es todo para la parte 2. Si desea profundizar en Flask, consulte la serie de videos que la acompañan:

Bonificación gratuita: Haga clic aquí para obtener acceso a un videotutorial gratuito de Flask + Python que le muestra cómo crear la aplicación web de Flask, paso a paso.

En la Parte 3, crearemos la función de conteo de palabras y la enviaremos a una cola de tareas para lidiar con el procesamiento de conteo de palabras de mayor duración.

Nos vemos la próxima vez. ¡Salud!

Esta es una pieza de colaboración entre Cam Linke, cofundador de Startup Edmonton, y la gente de Real Python.