J'ai essayé d'exécuter alembic, un outil de migration pour Python

Cible

Essayez d'exécuter le package de migration python alembic · PyPI

Qu'est-ce que l'alambic? ??

Un outil de migration qui gère votre base de données lors de l'utilisation de SQLAlchemy avec Python

Préparation environnementale

Créer un environnement avec Docker

Je veux le construire facilement, donc je le ferai avec Docker

Structure des dossiers


.
├── README.md
├── docker-compose.yml
└── src
    └── model.py

docker-compose.yml


version: "3"

services:
  db:
    image: postgres:11.7
    container_name: alembic-db
    ports:
      - 5432:5432
    environment:
      - POSTGRES_USER=postgres
      - POSTGRES_PASSWORD=postgres
      - POSTGRES_DB=almebic
  app:
    image: python:3.8.2-slim
    container_name: alembic-app
    volumes:
      - ./src:/usr/src
    environment:
      - PYTHONPATH=${PYTHONPATH}:/usr/src
    tty: true

Installer l'alambic

Installez les packages requis avec pip

pip install alembic psycopg2-binary

Si vous installez alambic, ** SQLAlchemy ** sera installé en même temps. ** psycopg2-binary · PyPI ** est utilisé pour se connecter à postgres

installation d'alambic


root@9a7582105665:/usr/src# pip install alembic psycopg2-binary
Collecting alembic
  Downloading alembic-1.4.2.tar.gz (1.1 MB)
     |████████████████████████████████| 1.1 MB 7.8 MB/s
  Installing build dependencies ... done
  Getting requirements to build wheel ... done
    Preparing wheel metadata ... done
Collecting psycopg2-binary
  Downloading psycopg2_binary-2.8.5-cp38-cp38-manylinux1_x86_64.whl (3.0 MB)
     |████████████████████████████████| 3.0 MB 32.3 MB/s
Collecting python-dateutil
  Downloading python_dateutil-2.8.1-py2.py3-none-any.whl (227 kB)
     |████████████████████████████████| 227 kB 23.8 MB/s
Collecting Mako
  Downloading Mako-1.1.2-py2.py3-none-any.whl (75 kB)
     |████████████████████████████████| 75 kB 11.2 MB/s
Collecting SQLAlchemy>=1.1.0
  Downloading SQLAlchemy-1.3.16-cp38-cp38-manylinux2010_x86_64.whl (1.2 MB)
     |████████████████████████████████| 1.2 MB 54.3 MB/s
Collecting python-editor>=0.3
  Downloading python_editor-1.0.4-py3-none-any.whl (4.9 kB)
Collecting six>=1.5
  Downloading six-1.14.0-py2.py3-none-any.whl (10 kB)
Collecting MarkupSafe>=0.9.2
  Downloading MarkupSafe-1.1.1-cp38-cp38-manylinux1_x86_64.whl (32 kB)
Building wheels for collected packages: alembic
  Building wheel for alembic (PEP 517) ... done
  Created wheel for alembic: filename=alembic-1.4.2-py2.py3-none-any.whl size=159543 sha256=dc29f47f6c24908d9413da7e3c969c64c252d0cbf9f90fca7cfbb5782b2452d0
  Stored in directory: /root/.cache/pip/wheels/70/08/70/cea787a7e95817b831469fa42af076046e55a05f7c94657463
Successfully built alembic
Installing collected packages: six, python-dateutil, MarkupSafe, Mako, SQLAlchemy, python-editor, alembic, psycopg2-binary
Successfully installed Mako-1.1.2 MarkupSafe-1.1.1 SQLAlchemy-1.3.16 alembic-1.4.2 psycopg2-binary-2.8.5 python-dateutil-2.8.1 python-editor-1.0.4 six-1.14.0

Vérifier la version du package


root@ecce2b20848e:/usr/src# pip list
Package         Version
--------------- -------
alembic         1.4.2
Mako            1.1.2
MarkupSafe      1.1.1
pip             20.1
psycopg2-binary 2.8.5
python-dateutil 2.8.1
python-editor   1.0.4
setuptools      46.1.3
six             1.14.0
SQLAlchemy      1.3.16
wheel           0.34.2

Créer un environnement alambic

Créer un environnement de migration avec alambic init

alembic init {Nom de l'environnement de migration}

Créez un environnement de migration avec

Réglage initial de l'alambic


root@ecce2b20848e:/usr/src# alembic init migration
  Creating directory /usr/src/migration ...  done
  Creating directory /usr/src/migration/versions ...  done
  Generating /usr/src/migration/README ...  done
  Generating /usr/src/alembic.ini ...  done
  Generating /usr/src/migration/env.py ...  done
  Generating /usr/src/migration/script.py.mako ...  done
  Please edit configuration/connection/logging settings in '/usr/src/alembic.ini' before proceeding.

Lorsque la création est terminée, il aura la structure suivante Vous pouvez voir que le ** répertoire de migration ** et le ** fichier alembic.ini ** sont créés

tree


.
├── README.md
├── docker-compose.yml
└── src
    ├── alembic.ini
    ├── migration
    │   ├── README
    │   ├── env.py
    │   ├── script.py.mako
    │   └── versions
    └── model.py

À propos des fichiers générés par alembic init

Lancer la migration

Modification de alembic.ini

Modifiez le fichier alembic.ini pour vous connecter à la base de données Réécrivez la partie suivante du fichier ini avec les informations de connexion à la base de données

alembic.ini (avant l'édition)


sqlalchemy.url = driver://user:pass@localhost/dbname

alembic.ini (après modification)


sqlalchemy.url = postgresql://postgres:postgres@alembic-db:5432/almebic

Utilisez les informations de connexion décrites dans ** docker-compose.yml **

Créer un fichier de migration

Créez un fichier de migration avec la commande ** revision **

alembic revision -m {nom de fichier}

Créer un fichier de migration


root@ecce2b20848e:/usr/src# alembic revision -m "create account table"
  Generating /usr/src/migration/versions/b5f586d58141_create_account_table.py ...  done

Après exécution, un fichier de migration sera créé sous le répertoire des versions.

b5f586d58141_create_account_table.py


"""create account table

Revision ID: b5f586d58141
Revises:
Create Date: 2020-05-02 17:49:20.493493

"""
from alembic import op
import sqlalchemy as sa


# revision identifiers, used by Alembic.
revision = 'b5f586d58141'
down_revision = None
branch_labels = None
depends_on = None


def upgrade():
    pass


def downgrade():
    pass

Modifier le fichier de migration

Modifier le fichier de migration généré Ici, nous copions l'officiel et créons un tableau de compte

b5f586d58141_create_account_table.py


"""create account table

Revision ID: b5f586d58141
Revises:
Create Date: 2020-05-02 17:49:20.493493

"""
from alembic import op
import sqlalchemy as sa


# revision identifiers, used by Alembic.
revision = 'b5f586d58141'
down_revision = None
branch_labels = None
depends_on = None


def upgrade():
    op.create_table(
        'account',
        sa.Column('id', sa.Integer, primary_key=True),
        sa.Column('name', sa.String(50), nullable=False),
        sa.Column('description', sa.Unicode(200)),
    )

def downgrade():
    op.drop_table('account')

Lancer la migration

Exécutez la migration avec la commande ** upgrade **

alembic upgrade head

** head ** effectuera la migration vers la dernière version Si vous ne souhaitez augmenter qu'une seule version, utilisez ** + 1 ** au lieu de head Si vous souhaitez abaisser la version, utilisez la commande ** downgrade ** Si vous souhaitez revenir à l'état initial

alembic downgrade base

Courir Utilisez ** -1 ** au lieu de base pour revenir à la version précédente

Lancer la migration


root@ecce2b20848e:/usr/src# alembic upgrade head
INFO  [alembic.runtime.migration] Context impl PostgresqlImpl.
INFO  [alembic.runtime.migration] Will assume transactional DDL.
INFO  [alembic.runtime.migration] Running upgrade  -> b5f586d58141, create account table

Générer automatiquement un fichier de migration

En éditant env.py comme dans Auto Generating Migrations - Alembic 1.4.2 documentation Il sera possible de créer automatiquement un fichier de migration à partir des informations du modèle ** SQLAlchemy ** défini en Python. Tout d'abord, définissez le modèle avec SQLAlchemy

Définition du modèle SQLAlchemy

Dans la définition du modèle, définissez la table de comptes ajoutée précédemment dans le modèle SQLAlchemy. Ajouter des colonnes pour ** created_at ** et ** updated_at ** Je veux passer le moteur SQLAlchemy à env.py, alors définissez-le

model.py


from datetime import datetime

from sqlalchemy import create_engine, Column, String, Integer, Unicode, DateTime
from sqlalchemy.ext.declarative import declarative_base

#Créer un moteur
Engine = create_engine(
    "postgresql://postgres:postgres@alembic-db:5432/almebic",
    encoding="utf-8",
    echo=False
)

'''
Créer une base de modèle
Si vous définissez un modèle basé sur cette base, les informations du modèle seront stockées dans des métadonnées.
'''
ModelBase = declarative_base()


class AcountModel(ModelBase):
    """
    AcountModel
    """
    __tablename__ = 'account'

    id = Column(Integer, primary_key=True)
    name = Column(String(50), nullable=False)
    description = Column(Unicode(200))
    created_at = Column(DateTime, default=datetime.now, nullable=False)
    updated_at = Column(DateTime, default=datetime.now, nullable=False)

Modification d'env.py

Modifiez env.py afin d'obtenir des informations sur le modèle défini dans model.py Importez les ** ModelBase ** et ** Engine ** définis précédemment au début Remplacez ** ModelBase.metadata ** par ** target_metadata ** Modifiez également ** run_migrations_online () ** lors de la migration afin que la migration soit effectuée.

env.py


from logging.config import fileConfig

from sqlalchemy import engine_from_config
from sqlalchemy import pool

from alembic import context
from model import ModelBase, Engine

# this is the Alembic Config object, which provides
# access to the values within the .ini file in use.
config = context.config

# Interpret the config file for Python logging.
# This line sets up loggers basically.
fileConfig(config.config_file_name)

# add your model's MetaData object here
# for 'autogenerate' support
# from myapp import mymodel
# target_metadata = mymodel.Base.metadata
target_metadata = ModelBase.metadata

# other values from the config, defined by the needs of env.py,
# can be acquired:
# my_important_option = config.get_main_option("my_important_option")
# ... etc.


def run_migrations_offline():
    """Run migrations in 'offline' mode.

    This configures the context with just a URL
    and not an Engine, though an Engine is acceptable
    here as well.  By skipping the Engine creation
    we don't even need a DBAPI to be available.

    Calls to context.execute() here emit the given string to the
    script output.

    """
    url = config.get_main_option("sqlalchemy.url")
    context.configure(
        url=url,
        target_metadata=target_metadata,
        literal_binds=True,
        dialect_opts={"paramstyle": "named"},
    )

    with context.begin_transaction():
        context.run_migrations()


def run_migrations_online():
    """Run migrations in 'online' mode.

    In this scenario we need to create an Engine
    and associate a connection with the context.

    """
    url = config.get_main_option("sqlalchemy.url")
    connectable = Engine

    with connectable.connect() as connection:
        context.configure(
            url=url,
            connection=connection,
            target_metadata=target_metadata
        )

        with context.begin_transaction():
            context.run_migrations()


if context.is_offline_mode():
    run_migrations_offline()
else:
    run_migrations_online()

Effectuer la migration à l'aide de la génération automatique

La commande revision avec l'option ** --autogenerate ** crée un fichier de migration à partir des informations de modèle définies dans SQLAlchemy.

commande de révision (--Avec autogénération)


root@9a7582105665:/usr/src# alembic revision --autogenerate -m "Added columns."
INFO  [alembic.runtime.migration] Context impl PostgresqlImpl.
INFO  [alembic.runtime.migration] Will assume transactional DDL.
INFO  [alembic.ddl.postgresql] Detected sequence named 'account_id_seq' as owned by integer column 'account(id)', assuming SERIAL and omitting
INFO  [alembic.autogenerate.compare] Detected added column 'account.created_at'
INFO  [alembic.autogenerate.compare] Detected added column 'account.updated_at'
  Generating /usr/src/migration/versions/dcd0d354f648_added_columns.py ...  done

Les fichiers suivants sont créés après l'exécution

dcd0d354f648_added_columns.py


"""Added columns.

Revision ID: dcd0d354f648
Revises: b5f586d58141
Create Date: 2020-05-02 18:58:03.864154

"""
from alembic import op
import sqlalchemy as sa


# revision identifiers, used by Alembic.
revision = 'dcd0d354f648'
down_revision = 'b5f586d58141'
branch_labels = None
depends_on = None


def upgrade():
    # ### commands auto generated by Alembic - please adjust! ###
    op.add_column('account', sa.Column('created_at', sa.DateTime(), nullable=False))
    op.add_column('account', sa.Column('updated_at', sa.DateTime(), nullable=False))
    # ### end Alembic commands ###


def downgrade():
    # ### commands auto generated by Alembic - please adjust! ###
    op.drop_column('account', 'updated_at')
    op.drop_column('account', 'created_at')
    # ### end Alembic commands ###

Après cela, la migration est terminée avec la commande de mise à niveau

prime

Que faire si je souhaite renommer le fichier généré par la migration?

Modifiez alembic.ini lorsque vous souhaitez modifier la convention de dénomination au lieu de dcd0d354f648_added_columns.py (par exemple, pour inclure des informations de date) Modifier ** file_template ** dans alembic.ini

Exemple


file_template = %%(year)d%%(month).2d%%(day).2d-%%(hour).2d%%(minute).2d_%%(slug)s

La génération automatique détectera-t-elle les modifications?

Veuillez noter que certaines modifications peuvent ne pas être détectées. Voir ci-dessous pour plus de détails Auto Generating Migrations — Alembic 1.4.2 documentation

Recommended Posts

J'ai essayé d'exécuter alembic, un outil de migration pour Python
J'ai essayé d'exécuter python à partir d'un fichier chauve-souris
[Python] J'ai essayé d'exécuter un serveur local en utilisant flask
J'ai essayé Grumpy (allez exécuter Python).
J'ai essayé d'exécuter prolog avec python 3.8.2.
J'ai essayé un langage fonctionnel avec Python
J'ai créé un outil de mot de passe en Python.
[5e] J'ai essayé de créer un certain outil de type Authenticator avec python
[2nd] J'ai essayé de créer un certain outil de type Authenticator avec python
[3ème] J'ai essayé de créer un certain outil de type Authenticator avec python
[4th] J'ai essayé de créer un certain outil de type Authenticator avec python
[1er] J'ai essayé de créer un certain outil de type Authenticator avec python
J'ai essayé d'exécuter pymc
J'ai essayé de jouer à un jeu de frappe avec Python
J'ai essayé Python> autopep8
J'ai essayé de lire un fichier CSV en utilisant Python
J'ai essayé d'exécuter faiss avec python, Go, Rust
J'ai essayé d'exécuter python -m summpy.server -h 127.0.0.1 -p 8080
J'ai essayé d'ajouter un module Python 3 en C
J'ai essayé d'exécuter Deep Floor Plan avec Python 3.6.10.
J'ai essayé Python> décorateur
J'ai essayé d'exécuter TensorFlow
J'ai essayé d'implémenter ce qui semble être un outil de snipper Windows avec Python
J'ai essayé d'implémenter un pseudo pachislot en Python
J'ai essayé de dessiner une pseudo figure fractale en utilisant Python
J'ai essayé d'utiliser Python (3) au lieu d'un calculateur de fonctions
Python: j'ai essayé menteur et honnête
J'ai essayé fp-growth avec python
J'ai essayé de gratter avec Python
J'ai essayé l'extension C de Python
J'ai fait un texte Python
J'ai essayé de gratter avec du python
J'ai essayé d'implémenter un automate cellulaire unidimensionnel en Python
[Chaîne de Markov] J'ai essayé de lire les citations en Python.
J'ai essayé "un programme qui supprime les déclarations en double en Python"
J'ai essayé d'utiliser Tensorboard, un outil de visualisation pour l'apprentissage automatique
J'ai essayé "Comment obtenir une méthode décorée en Python"
J'ai créé une classe en Python et essayé de taper du canard
J'ai fait un chronomètre en utilisant tkinter avec python
J'ai essayé de simuler la probabilité d'un jeu de bingo avec Python
J'ai essayé de toucher Python (installation)
J'ai essayé webScraping avec python.
J'ai fait une loterie avec Python.
J'ai essayé d'exécuter GAN dans Colaboratory
J'ai essayé d'utiliser Thonny (Python / IDE)
[Python] Mémo de création de l'outil de grattage
J'ai créé un démon avec Python
J'ai essayé la notification de ligne en Python
J'ai essayé la communication SMTP avec Python
J'ai essayé de transformer un fichier Python en un EXE (erreur de récursivité prise en charge)
J'ai essayé d'exécuter le référentiel de packages Python (entrepôt) qui prend en charge PyPI
J'ai essayé de créer une expression régulière de "montant" en utilisant Python
J'ai essayé de créer une expression régulière de "temps" en utilisant Python
[Python] Un mémo que j'ai essayé de démarrer avec asyncio
J'ai essayé d'exécuter Platypus qui peut résoudre un petit problème d'optimisation - Partie 2
J'ai essayé de créer une liste de nombres premiers avec python
J'ai essayé de créer une expression régulière de "date" en utilisant Python
J'ai essayé de mettre en œuvre un jeu de dilemme de prisonnier mal compris en Python