asyncpg を使用して接続するデータベースを持つ非同期 Python アプリケーションがあり、すべてのクエリを手動で入力することを避けたいと考えています。sqlalchemy コアが非常に役立つことがわかりましたが、1 つのことに苦労しています。アプリケーションが既に作成されていることに依存するのではなく、起動時にデータベーススキーマを作成できるようにしたいのですが、そうする自動方法が見つかりません。私が欲しいのは次のようなものです:
import asyncio
from sqlalchemy import Table, Column, Integer, String, MetaData
import asyncpg
metadata = MetaData()
people = Table(
"people",
metadata,
Column("id", Integer, primary_key=True, autoincrement=True),
Column("name", String)
)
class Database:
def __init__(self, pool: asyncpg.pool.Pool):
self.pool = pool
async def ensure_schema(self):
async with self.pool.acquire() as con:
await con.execute(
# this method doesn't really exist,
# I'm just looking for something that would
# do the same - return following query:
# CREATE TABLE IF NOT EXISTS people(id INTEGER PRIMARY KEY, name VARCHAR)
people.get_create_query(checkfirst=True)
)
async def main()
pool = await asyncpg.create_pool(host="127.0.0.1", port=5432, user="postgres", password="postgres", database="test")
db = Database(pool)
await db.ensure_schema()
if __name__ == "__main__":
loop = asyncio.get_event_loop()
loop.run_until_complete(main())
ここでの問題は、sqlalchemymetadata
がエンジンにバインドされることを期待しているが、非同期エンジンをサポートしていないことです。したがって、宣言されたテーブルから CREATE クエリ文字列を取得し、それを接続に渡して実行したいだけです。
これの類推はpeople.select()
、すぐには実行されないかもしれません。実行されるクエリである文字列表現も持つオブジェクトを作成するだけです。
SQL スキーマを別のファイルに格納して起動時にロードすることはできますが、スキーマを変更するたびにコード内の 2 か所で変更する必要があるため、適切ではありません。助言がありますか?