Lento con forza

大学生気分のIT系エンジニアが色々書いてく何か。ブログ名決めました。

SQLAlchemyでsqlite3の外部キー制約を有効にする方法

ここ最近ずっとSQLAlchemyを使ってます。
ORM使っても、結局SQL考えながら書くし、今までSQL使ってた人に取っては、「SQLだったらこう書くのにORMだとわからん!!!:ってのが多発してすごく大変です。
まぁ、そんなことはどうでもいいので本題へ!

SQLite3はデフォルトで外部キー制約が無効

SQLite3ってデフォルトでは外部キー制約が無効なんですよね。
SQLAlchemyで生成されたSQLではFOREIGN KEY制約がついていたのですが、これだけではダメで明示的に外部キーを利用することを伝えてあげないとあげないとダメみたいです。

僕はSQLiteで開発しつつ、本番はMySQLで。というパターンで開発しています。実はリリース時に外部キー制約に引っかかってたなんて事になるのは嫌ですよね。そのため、SQLAlchemyで外部キーを有効にする方法を調べてました

大切なことはいつもStackoverflowが教えてくれた

ここのStackoverflowで全て教えてくれました。

SQLAlchemyのengineを作る時の処理を、以下のように書き換えればいいそうです。

from sqlalchemy.interfaces import PoolListener
class ForeignKeysListener(PoolListener):
    def connect(self, dbapi_con, con_record):
        db_cursor = dbapi_con.execute('pragma foreign_keys=ON')

url = 'sqlite://'
engine = sqlalchemy.create_engine(url, listeners=[ForeignKeysListener()], echo=True)

この例はsqliteのインメモリDBを使うときの書き方です。

engineを作る時にこのクラスをlistenersに指定することで、外部キー制約違反の時にエラーで教えてくれるようになりました。かいけつかいけつ!