[PYTHON] Au milieu du développement, nous présenterons Alembic

Je souhaite gérer la version du schéma DB

Je pensais que je le ferais correctement, alors j'ai ajouté Alembic.

Gestion des versions de schéma de base de données ~? http://www.slideshare.net/kwatch/db-28097225

C'est la meilleure référence pour l'installation et l'utilisation de base, donc je pense que tout va bien http://momijiame.tumblr.com/post/45191790683/python-alembic-rdb

Facile à introduire même pendant le développement

Au fait, dans mon cas cette fois, puisque j'ai déjà commencé à faire une application, il existe déjà des définitions de modèles de SQLAlchemy, et bien sûr il y a déjà une table dans DB, quelle est cette table dans le script de migration d'Alembic à nouveau Dois-je écrire toutes les définitions de op.create_table? sérieusement? C'est dur ... C'est aussi dur qu'une guerre ... Mais c'est plus dur qu'une guerre ...

J'ai pensé, mais il existe une fonction pour lire correctement les définitions de DB et SQLAlchemy et générer automatiquement un script de migration.

http://alembic.readthedocs.org/en/latest/tutorial.html#auto-generating-migrations

Un enfant qui peut. Cet enfant peut laisser son portefeuille. Alors je vais essayer cette rue.

Génération automatique du script de migration

On suppose que le réglage initial de l'Alembic est terminé en référence au premier site. Cependant, après avoir fait ʻalembic init, si sqlalchemy.url` est correctement défini dans le fichier alembic.ini créé, il sera connecté à la base de données, alors peut-être que c'est OK.

Donc, le sujet principal. Je vous indiquerai l'emplacement de la base de votre application comme source de génération automatique.

env.py


import webapp.model.database
target_metadata = Base.metadata

Il semble que ce soit tout ce dont vous avez besoin. Créons le premier script de migration. Si vous ajoutez --autogenerate, il fera quelque chose automatiquement. incroyable. C'est automatique ~ j'aime ça! Une machine mochitsuki automatique!

Avant cela, supprimez ici une fois toutes les tables du DB.

La génération automatique semble détecter la différence entre les métadonnées DB et SQL Alchemy. Le premier script à être généré automatiquement à partir de maintenant est un script de génération de table, donc la base de données doit être vide. N'est-ce pas? Je m'en fiche.

Donc, j'ai une fois supprimé toutes les tables DB. Après cela, tapez la commande immédiatement.

$ alembic revision --autogenerate -m "Create table"

J'ai pu faire quelque chose sous alebmic / versions /! La tension monte! Si vous ne pouvez pas, c'est probablement parce que Base n'a pas été importée correctement.

# revision identifiers, used by Alembic.
revision = '30552bc9b83'
down_revision = None

from alembic import op
import sqlalchemy as sa
from sqlalchemy.dialects import postgresql

def downgrade():
    ### commands auto generated by Alembic - please adjust! ###
    op.drop_table('order_logs')
    op.drop_table('order_items')
    op.drop_table('users')
    ### end Alembic commands ###


def upgrade():
    ### commands auto generated by Alembic - please adjust! ###
    op.create_table('users',
    sa.Column('id', sa.INTEGER(), primary_key=True),
    sa.Column('name', sa.TEXT(), autoincrement=False, nullable=True),
    sa.Column('mail_address', sa.TEXT(), autoincrement=False, nullable=True),
    sa.Column('password', sa.TEXT(), autoincrement=False, nullable=True),
    sa.Column('status', sa.INTEGER(), autoincrement=False, nullable=True),
    sa.Column('insert_date', postgresql.TIMESTAMP(), autoincrement=False, nullable=True),
    sa.Column('update_date', postgresql.TIMESTAMP(), autoincrement=False, nullable=True),
    sa.PrimaryKeyConstraint('id', name='users_pkey')
    )
    op.create_table('order_items',
    sa.Column('id', sa.INTEGER(), primary_key=True),
    sa.Column('order_log_id', sa.INTEGER(), autoincrement=False, nullable=True),
    sa.Column('user_id', sa.INTEGER(), autoincrement=False, nullable=True),
    sa.Column('item_name', sa.TEXT(), autoincrement=False, nullable=True),
    sa.Column('item_price', sa.INTEGER(), autoincrement=False, nullable=True),
    sa.Column('item_number', sa.INTEGER(), autoincrement=False, nullable=True),
    sa.Column('item_total', sa.INTEGER(), autoincrement=False, nullable=True),
    sa.Column('status', sa.SMALLINT(), autoincrement=False, nullable=True),
    sa.Column('insert_date', postgresql.TIMESTAMP(), autoincrement=False, nullable=True),
    sa.Column('update_date', postgresql.TIMESTAMP(), autoincrement=False, nullable=True),
    sa.PrimaryKeyConstraint('id', name='order_items_pkey')
    )
    op.create_table('order_logs',
    sa.Column('id', sa.INTEGER(), primary_key=True),
    sa.Column('user_id', sa.INTEGER(), autoincrement=False, nullable=True),
    sa.Column('order_no', sa.TEXT(), autoincrement=False, nullable=True),
    sa.Column('order_name', sa.TEXT(), autoincrement=False, nullable=True),
    sa.Column('order_name_kana', sa.TEXT(), autoincrement=False, nullable=True),
    sa.Column('order_zip', sa.TEXT(), autoincrement=False, nullable=True),
    sa.Column('order_address', sa.TEXT(), autoincrement=False, nullable=True),
    sa.Column('order_mail_address', sa.TEXT(), autoincrement=False, nullable=True),
    sa.Column('order_phone_number', sa.TEXT(), autoincrement=False, nullable=True),
     sa.Column('total', sa.INTEGER(), autoincrement=False, nullable=True),
    sa.Column('status', sa.SMALLINT(), autoincrement=False, nullable=True),
    sa.Column('insert_date', postgresql.TIMESTAMP(), autoincrement=False, nullable=True),
    sa.Column('update_date', postgresql.TIMESTAMP(), autoincrement=False, nullable=True),
    sa.PrimaryKeyConstraint('id', name='order_logs_pkey')
    )

Comme c'est gentil! Maintenant, essayez d'exécuter ```upgrade () du script de migration que vous avez créé.

$ alembic upgrade head

Une table a été créée dans le DB!

Essayez de rétrograder.

$ alembic downgrade -1

La table a disparu de la base de données! (Parce qu'il était vide il y a une fois)

$ alembic upgrade +1

C'est refait! Trop obéissant! Vous pouvez y aller une fois!

Vous pouvez continuer à ressentir la même chose après cela

Après cela, lors de la modification de la définition de la table, je vais créer un script de migration avec Alembic et jouer avec la base de données.

Si vous effectuez une autre alembic revision --autogenerate après avoir réécrit la définition de la table côté SQLAlchemy, un script de migration pour la différence sera créé automatiquement par rapport à l'état de la base de données. Uhyo ~! !!

Tellement bien, les choses que je fais sont presque les mêmes,

  1. Jouez avec la définition de table SQLAclhemy
  2. Lors de la réflexion vers DB, la ```alembic revision --autogenerate -m "hoge" d'Alembic au lieu de drop () `` create () de SQLAlchemy Suivez simplement les étapes ʻet `ʻalembic upgrade + 1 ''

J'ai pensé que ce serait bien si je pouvais le réparer quand j'ai dit que c'était mauvais.

Autres choses que j'ai remarquées en utilisant

Vous pouvez émettre la définition de table par erreur

alembic revision --autogenerateAprès avoir émis un nouveau script de migration dans, s'il n'y a pas une telle chose maintenant, il semble que vous puissiez simplement supprimer le script généré. Ample.

C'est bon parce que c'est lâche même si vous le lancez mal et l'appliquez

Si vous trouvez une erreur dans le script de migration après l'avoir appliqué à la base de données, utilisez alembic downgrade -1 pour ramener la base de données à l'état précédent, corrigez le script et alembic upgrade + 1 Deyosage. Ample.

Il y a une limite à la génération automatique

Alembic n'a pas reconnu la différence avec les valeurs par défaut et les clés externes. C'est un peu décevant car je dois écrire le script à la main. Au fait http://alembic.readthedocs.org/en/latest/tutorial.html#auto-generating-migrations Vers la fin, il y a une liste de choses qui peuvent être trouvées comme des différences, des choses que vous ne pouvez pas trouver et des choses que vous ne pouvez pas trouver. Eh bien, ce genre de sentiment.

J'ai l'impression que la fonction n'est pas bien convertie

Par exemple, dans la définition du modèle, la valeur par défaut est l'heure actuelle,

insert_date = Column(DateTime, server_default=func.now())

Quand je l'ai fait, le scénario que j'allais faire était comme ça.

sa.Column('insert_date', sa.DateTime(), server_default=func.now(), nullable=True),

C'est mauvais, et si vous faites cela par inadvertance, func.now () sera évalué à la volée et la valeur par défaut sera fixée à la date à laquelle vous l'avez exécutée, par exemple 2014/1/1 00: 00: 00 Devenir.

Maintenant script manuellement

sa.Column('insert_date', sa.DateTime(), server_default=sa.func.now(), nullable=True),

Je l'exécute après l'avoir réécrit, mais je ne suis pas doué pour ça ... Quelqu'un peut-il me le dire ...

La fin

Recommended Posts

Au milieu du développement, nous présenterons Alembic
Maintenance de l'environnement de développement Django + MongoDB (en cours d'écriture)
#Nous automatiserons l'agrégation des données de Wiire! partie 1
Une histoire sur la tentative d'introduire Linter au milieu d'un projet Python (Flask)
[Astuces] Problèmes et solutions dans le développement de python + kivy
django ne peut pas être installé dans l'environnement de développement de pipenv + pyenv
L'histoire de la participation à AtCoder
Supprimer les sauts de page au milieu d'un tableau avec sphinx single html
L'histoire du "trou" dans le fichier
Utilisation de TensorFlow dans l'environnement de développement intégré Cloud 9 - Principes d'utilisation -
Lignes directrices pour se réincarner dans le monde du développement de programmation Linux (langage C / C ++)
Depuis que nous avons publié DataLiner 1.2.0, nous allons introduire le nouveau prétraitement ajouté.
Avec l'avènement de systemd-homed en 2020, la gestion des utilisateurs Linux changera radicalement.
[Comprendre en 3 minutes] Le début de Linux
Vérifiez le comportement du destroyer en Python
Gymnastique algorithmique 24 Milieu de la liste liée
Le résultat de l'installation de python sur Anaconda
Principes de base pour exécuter NoxPlayer en Python
Obtenez la valeur de la couche intermédiaire de NN
À la recherche du FizzBuzz le plus rapide en Python
Vous serez ingénieur dans 100 jours - Jour 29 - Python - Bases du langage Python 5
Vous serez ingénieur dans 100 jours - Jour 33 - Python - Bases du langage Python 8
Vous serez ingénieur dans 100 jours --Jour 26 --Python --Basiques du langage Python 3
Pour générer une valeur au milieu d'une cellule avec Jupyter Notebook
Vous serez ingénieur dans 100 jours --Jour 32 --Python --Basiques du langage Python 7
Maintenant que je connais le système de paquets, je vais vous présenter Hello World
Vous serez ingénieur dans 100 jours --Jour 28 --Python --Les bases du langage Python 4
Sortie du nombre de cœurs de processeur en Python
Signification de {numéro de version} dans le package mysql rpm
[Python] Trier la liste de pathlib.Path dans l'ordre naturel
Changer la taille de police de la légende dans df.plot
Faites correspondre la distribution de chaque groupe en Python
Afficher le résultat du traitement de la géométrie en Python
Instanciation de l'environnement de développement BOX créé précédemment
Copiez la liste en Python
Trouvez le nombre de jours dans un mois
Lire la sortie du sous-processus, ouvrir en temps réel
Découvrez la fraction de la valeur saisie en python
L'histoire de la recherche du n optimal dans N poing
Correction des arguments de la fonction utilisée dans map
À propos du contenu de développement de l'apprentissage automatique (exemple)
Trouvez la solution de l'équation d'ordre n avec python
L'histoire de la lecture des données HSPICE en Python
[Note] À propos du rôle du trait de soulignement "_" en Python
Résolution d'équations de mouvement en Python (odeint)
Visualisation de l'état d'utilisation de l'évier dans l'entreprise
Sortie sous la forme d'un tableau python
L'histoire de l'affichage des fichiers multimédias dans Django
Rechercher par la valeur de l'instance dans la liste
Rendre la progression de dd visible sur la barre de progression