ビジネスパーソン・ガジェット置場 empty lot for business

営業や仕事、それに伴う生活を便利に楽にするツール、ガジェットを作ります。既にあるツールも自分用にカスタマイズ。

python: Flask migrationエラー

備忘録です。

Flaskでアプリケーションを作っているときに、何度か遭遇したmigrationエラーについて。

エラー

データベース更新時のエラーについて

把握しきれていないのですが、Flaskでアプリケーションの作成時にSQLAlchemyを使用している時にでたエラーについて対処してみた方法について備忘録でまとめます。

下記エラーはローカルで開発時にでたエラーになります。

 

1. error “flask migrate target database is not up to date” Code Answer

 

既存のテーブルにカラムを追加した際にでたエラーです。エラーが出ることでカラムの追加が反映されない状態になります。

 

エラーが出た際のapp.pyの実装状態は下記。

from flask_sqlalchemy import SQLAlchemy

app = Flask(__name__)
db = SQLAlchemy(app)
migrate = Migrate(app, db)

 

下記のサイトを参考にしたところエラーが解除されました。

https://www.codegrepper.com/code-examples/sql/flask+migrate+target+database+is+not+up+to+date

 

ターミナルで実行したことは下記の1行目を追加して実行しました。

$ flask db stamp head
$ flask db migrate
$ flask db upgrade

 

 

2. error Flask Migrate "ValueError: Constraint must have a name"

 

1でテーブルにカラムを追加できていたのですが、同様にテーブルの追加やカラムの追加をしていたときに、上記のエラーが発生。

 

app.pyの実装状態は1と同じ形。

 

こちらは、下記のサイトで書かれていることを実装して対処してみました。

Flask Migrate "ValueError: Constraint must have a name" - Stack Overflow

 

from sqlalchemy import MetaData

convention = {
    "ix": 'ix_%(column_0_label)s',
    "uq": "uq_%(table_name)s_%(column_0_name)s",
    "ck": "ck_%(table_name)s_%(constraint_name)s",
    "fk": "fk_%(table_name)s_%(column_0_name)s_%(referred_table_name)s",
    "pk": "pk_%(table_name)s"
}

metadata = MetaData(naming_convention=convention)
db = SQLAlchemy(app, metadata=metadata)

 

DBにカラムも追加されて更新されていましたが、upgrade時にエラーがどうしてもでてる形。そのエラーが次のエラー。

 

3. ERROR [flask_migrate] Error: No support for ALTER of constraints in SQLite dialect. Please refer to the batch mode feature which allows for SQLite migrations using a copy-and-move strategy

 

そして下記のサイトを参考に対応。

Python Friday #88: Activate Batch Mode in Alembic to Work With Constraints in SQLite – Improve & Repeat

 

これでエラーが何もでなくなりしっかりとカラムも更新されていた。

今後、もっと細かいところまで理解しないとダメだなー。

 

ちなみにエラーが出なくなった段階の実装状況はこちら

 

# app.py

from flask_sqlalchemy import SQLAlchemy
from sqlalchemy import MetaData

convention = {
    "ix": 'ix_%(column_0_label)s',
    "uq": "uq_%(table_name)s_%(column_0_name)s",
    "ck": "ck_%(table_name)s_%(constraint_name)s",
    "fk": "fk_%(table_name)s_%(column_0_name)s_%(referred_table_name)s",
    "pk": "pk_%(table_name)s"
}

# データベースの初期化
metadata = MetaData(naming_convention=convention)
db = SQLAlchemy(app, metadata=metadata)
migrate = Migrate(app, db)

 

# migrations/env.py

def run_migrations_offline():

   (中略)

    context.configure(
        url=url, target_metadata=target_metadata, literal_binds=True, render_as_batch=True
    )

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


def run_migrations_online():
    
   (中略)

    with connectable.connect() as connection:
        context.configure(
            connection=connection,
            target_metadata=target_metadata,
            render_as_batch=True,
            process_revision_directives=process_revision_directives,
            **current_app.extensions['migrate'].configure_args
        )