Reflecting Database Objects


Official SQLAlchemy 1.4 Document: Reflecting Database Objects
DigiFinanceというTAMSというサービスアプリケーションのAPI v 1、v 2再構築を担当しています.データベースがどのように機能しているかは、残されたコードから理解していますが、SQLAlchemy ORMを使用するのは想像以上に難しいです.まだうろうろしていて、いろいろな方法を試しています.
DjangoとDjango ORMの2つの非常に自動化された便利なフレームワークのみを使用し、FlaskベースのAPIをSQLChemyoRMとしてデータベースと連動させる方法について長い間うろうろしていました.
現在進行中ですが、SQLAlchemyではデータベース・アーキテクチャがすでに存在する場合は、直接ロードして使用方法を提供できます.(調べてみるとDjangoにも似たような方法があります)既存のデータベースのパターンをモデルに直接インポートします.もう1つのsqlacodegenというライブラリはpyを自動的に生成することができます.sqlacodegenの使用方法ですが、現在のプロジェクトではこのライブラリは使用されません.
これらのプロセスはReflectionと呼ばれ、その名の通り、既存のデータベースを反映しているようです.テーブルの名前とメタデータオブジェクト、およびautoload withパラメータを知るだけで、既存のDBを読み込むことができます.
> messages = Table('message', meta, autoload_with = engine) 
> c.name for c in messages.columns]
['message_id', 'message_name', 'data']
以上のコードは、エンジンによって「message」というテーブルの情報をクエリーにインポートする方法です.テーブル内のColumn、ForeignKey、その他の情報に関連するオブジェクトを作成します.
テーブルが反映されると、テーブルが外部キーで別のテーブルを参照している場合は、2番目のテーブルがmetadataオブジェクト内で作成され、接続されていることを示します.次のコードを見てください.shopping cart itemsというテーブルがshopping cartsというテーブルを参照していると仮定します.shopping cart itemsという名前のテーブルを読み込むと、shopping cartsテーブルも自動的に読み込まれます.
> shopping_cart_items = Table('shopping_cart_items', meta, autoload_with=engine)
> 'shopping_carts' in meta.tables:
True
Metadataは「singleton-like」動作を有する.各テーブルの読み込みが要求されると、metadataは単一のTableオブジェクトにそれぞれ異なるテーブル名を作成します.同じ名前のTableが既に存在する場合、Table constructorは既存のTableオブジェクトを読み込みます.
shopping_carts = Table('shopping_carts', meta)
もちろん、autoload_with = engineを使用するのは表に関係ありません.Autoload with機能には、テーブルのプロパティが正しく反映されていない場合に自動的にロードされる機能があります.自動ロード機能は、テーブルが正しくロードされていないテーブルにのみ適用されます.インポートが適用されている場合、既存のテーブルとクエリーには影響しません.
Code example
from sqlalchemy import create_engine
from sqlalchemy import MetaData, Table
from flask_sqlalchemy import declarative_base

DB_URL = f"mysql+mysqldb://{app.config['MYSQL_USER']}:{app.config['MYSQL_PASSWORD']}@
	{app.config['MYSQL_HOST']}:{int(app.config['MYSQL_PORT'])}/{app.config['MYSQL_DB']}?charset=utf8mb4"
database = create_engine(DB_URL, encoding='utf-8', max_overflow=DevConfig.DB_MAX_OVERFLOW,
                             pool_recycle=DevConfig.DB_POOL_RECYCLE, pool_size=DevConfig.DB_POOL_SIZE)

Base = declarative_base()
metadata = MetaData(bind=database)
Base.metadata.create_all(database)

trv_user = Table('trv_user', metadata, autoload_with=database)
inactive_users = Table('inactive_users', metadata, autoload_with=database)
user_action_log = Table('user_action_log', metadata, autoload_with=database)
user_certificate = Table('user_certificate', metadata, autoload_with=database)
wallet_balance = Table('wallet_balance', metadata, autoload_with=database)
user_cache_tbl = Table('user_cache_tbl', metadata, autoload_with=database)
上記のコードは、実際にAPIのTAMSという既存のデータベースのテーブルをインポートするために使用されるコードです.
Declare
from sqlalchemy.ext.declarative import declarative_base

base = declarative_base()   # 객체 생성
ORMを使用するときに使用するデータベース・テーブルを説明し、そのテーブルにマッピングされる独自のクラスを定義する必要があります.SQLAlchemyでは、通常、この2つのタスクはDeclariteで実行できます.
アプリケーションには、通常、インポートされたモジュール・データベース・インスタンスが1つしかありません.これらのベースクラスは、declarative_base()関数によって作成できます.declarative_base()を継承する必要があるすべてのマッピングクラスから新しいベースクラスが返されます.
また、マッピングクラスでは、データベースcolumnを示すcolumnクラス、各カラムのデータ型を示すInteger, Stringクラスをロードする必要がある.