備忘録です。
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
)