- SQL Expression LanguageはSQLAlchemy CoreとORMの中心的な要素となり,SQLクエリの構成を可能とする
- これらクエリの基礎になるのが,データベースの要素を表・列のように表現するPythonオブジェクト
Table型オブジェクトでMetaDataを用意
- SQLQlchemyにおけるデータベースメタデータの基本オブジェクト
- MetaData
- Table
- データベースのテーブルを表す
- 自身をMetaData collectionへと割り当てる
- Column
- データベースのテーブルのカラムを表す
- 自身をテーブルオブジェクトに割り当てる
- str型の名前とタイプオブジェクトを含む
- Table.columnsでテーブルのColumnCollectionにアクセス
- Table.columns.keys(): 全カラムの名前をList[str]として受け取れる
- Table.primary_key: テーブルの主キー
# テーブルの定義 >>> from sqlalchemy import MetaData >>> metadata = MetaData() >>> from sqlalchemy import Table, Column, Integer, String >>> user_table = Table( ... "user_account", ... metadata, ... Column('id', Integer, primary_key=True), ... Column('name', String(30)), ... Column('fullname', String) ... ) >>> user_table.c.name Column('name', String(length=30), table=<user_account>) >>> user_table.c.keys() ['id', 'name', 'fullname'] # 別テーブルのカラムを使う >>> from sqlalchemy import ForeignKey >>> address_table = Table( ... "address", ... metadata, ... Column('id', Integer, primary_key=True), ... Column('user_id', ForeignKey('user_account.id'), nullable=False), ... Column('email_address', String, nullable=False) ... )
データベースにData Definition Language (DDL)を送る?
- 作成したメタデータを元にデータベースにデータをinsertする/からデータをqueryするためには以下のどちらかをSALite データベースにemitする
- CREATE TABLE statement
- Data Definition Language (DDL)
- 以下のコードを実行すると,対象とするデータベースを参照しているEngineにメタデータを送る
metadata.create_all(engine)
ORMを使ってテーブルのメタデータを定義
上述した例をORMを使って実現
- mappedクラスを宣言する過程でTableメタデータを宣言
- mappedクラスはどのようなPythonのクラスでも良く,データベーステーブル内のカラムにリンク付けされる属性を持つ
何種類かの方法があるけど,最も一般的なスタイルはdeclarative
Registryのセットアップ
- MetaDataコレクションがありORMを使う時,registryを生成する
- registryを生成するときに,自動的にMetaDataオブジェクトがインクルードされる
- Tableオブジェクトを直接宣言する代わりに,mappedクラスへのdirectivesを通して間接的に宣言する
- この間接的な宣言をする一般的なやり方は,registry.generate_base()を使ってdeclarative baseを取得する
- Mapped classの宣言
- BaseオブジェクトはORM mapped classのための基底クラスになる
- テーブル毎にORM mapped classを定義する
- init()は自動的に生成される (メンバ変数はクラス直下にベタ書き)
- 全てのカラム名と同じ変数名のメンバ変数を定義し,そのタイプはColumn型のオブジェクト
- repr()はフォーマット文字列(f"...")で,そのクラスのオブジェクトを返す
- メンバ変数 table を使ってdeclarative mapped classからTableオブジェクトを見れる
- ORMでDDLをデータベースへemit
- Coreと同様にMetaData.create_all()を使う
- registryと関連付けアレたMetaDataとORM declarative base classを利用
# registryの生成 >>> from sqlalchemy.orm import registry >>> mapper_registry = registry() # 自動的にインクルードされるMetaData (何も含んでいないことが分かる) >>> mapper_registry.metadata MetaData() # declarative baseを取得 >>> Base = mapper_registry.generate_base() >>> from sqlalchemy.orm import relationship # userテーブルのためのORM mapped class >>> class User(Base): ... __tablename__ = 'user_account' ... ... id = Column(Integer, primary_key=True) ... name = Column(String(30)) ... fullname = Column(String) ... ... addresses = relationship("Address", back_populates="user") ... ... def __repr__(self): ... return f"User(id={self.id!r}, name={self.name!r}, fullname={self.fullname!r})" # addressテーブルのためのORM mapped class >>> class Address(Base): ... __tablename__ = 'address' ... ... id = Column(Integer, primary_key=True) ... email_address = Column(String, nullable=False) ... user_id = Column(Integer, ForeignKey('user_account.id')) ... ... user = relationship("User", back_populates="addresses") ... ... def __repr__(self): ... return f"Address(id={self.id!r}, email_address={self.email_address!r})" # emit CREATE statements given ORM registry mapper_registry.metadata.create_all(engine) # the identical MetaData object is also present on the # declarative base Base.metadata.create_all(engine)