Declarative Mapping Styles¶
Declarative Mapping で紹介されているように、 Declarative Mapping は、現代のSQLAlchemyでマッピングを構築する典型的な方法です。このセクションでは、宣言的マッパーの設定に使用できるフォームの概要を説明します。
Using a Declarative Base Class¶
最も一般的なアプローチは、 DeclarativeBase
スーパークラスをサブクラス化して “DeclarativeBase” クラスを生成することです:
from sqlalchemy.orm import DeclarativeBase
# declarative base class
class Base(DeclarativeBase):
pass
Declarative Baseクラスは、既存の registry
を registry
という名前のクラス変数として割り当てることによって作成することもできます:
from sqlalchemy.orm import DeclarativeBase
from sqlalchemy.orm import registry
reg = registry()
# declarative base class
class Base(DeclarativeBase):
registry = reg
Changed in version 2.0: The DeclarativeBase
superclass supersedes
the use of the declarative_base()
function and
registry.generate_base()
methods; the superclass approach
integrates with PEP 484 tools without the use of plugins.
See ORM Declarative Models for migration notes.
宣言的な基底クラスでは、新しいマップされたクラスは基底のサブクラスとして宣言されます。:
from datetime import datetime
from typing import Optional
from sqlalchemy import ForeignKey
from sqlalchemy import func
from sqlalchemy import Integer
from sqlalchemy import String
from sqlalchemy.orm import DeclarativeBase
from sqlalchemy.orm import Mapped
from sqlalchemy.orm import mapped_column
from sqlalchemy.orm import relationship
class Base(DeclarativeBase):
pass
class User(Base):
__tablename__ = "user"
id = mapped_column(Integer, primary_key=True)
name: Mapped[str]
fullname: Mapped[Optional[str]]
nickname: Mapped[Optional[str]] = mapped_column(String(64))
create_date: Mapped[datetime] = mapped_column(insert_default=func.now())
addresses: Mapped[List["Address"]] = relationship(back_populates="user")
class Address(Base):
__tablename__ = "address"
id = mapped_column(Integer, primary_key=True)
user_id = mapped_column(ForeignKey("user.id"))
email_address: Mapped[str]
user: Mapped["User"] = relationship(back_populates="addresses")
上記では、 Base
クラスは、マップされる新しいクラスのベースとして機能します。上記では、新しいマップされたクラス User
と Address
が構築されます。
構築された各サブクラスに対して、クラスの本体は、完全なマッピングを構成する舞台裏で Table
と Mapper
オブジェクトの両方を定義する宣言的なマッピング手法に従います。
See also
Table Configuration with Declarative - 生成されるマップされた Table
のコンポーネントを指定する方法を説明します。これには、 mapped_column()
構文の使用に関する注意とオプション、および Mapped
アノテーションタイプとの相互作用方法が含まれます。
Mapper Configuration with Declarative - relationship()
の設定、SQL式、 Mapper
のパラメータなど、宣言型内のORMマッパー設定の他のすべての側面を記述します。
Declarative Mapping using a Decorator (no declarative base)¶
“declarative base”クラスを使用する代わりに、宣言マッピングをクラスに明示的に適用することができます。これは、”古典的な”マッピングと同様の命令的な手法を使用するか、デコレータを使用してより簡潔に行います。 registry.mapped()
関数は、階層が存在しない任意のPythonクラスに適用できるクラスデコレータです。それ以外の場合、Pythonクラスは通常、宣言スタイルで設定されます。
以下の例では、 DeclarativeBase
スーパークラスではなく、 registry.mapped()
デコレータを使用して、前のセクションと同じマッピングを設定しています。:
from datetime import datetime
from typing import List
from typing import Optional
from sqlalchemy import ForeignKey
from sqlalchemy import func
from sqlalchemy import Integer
from sqlalchemy import String
from sqlalchemy.orm import Mapped
from sqlalchemy.orm import mapped_column
from sqlalchemy.orm import registry
from sqlalchemy.orm import relationship
mapper_registry = registry()
@mapper_registry.mapped
class User:
__tablename__ = "user"
id = mapped_column(Integer, primary_key=True)
name: Mapped[str]
fullname: Mapped[Optional[str]]
nickname: Mapped[Optional[str]] = mapped_column(String(64))
create_date: Mapped[datetime] = mapped_column(insert_default=func.now())
addresses: Mapped[List["Address"]] = relationship(back_populates="user")
@mapper_registry.mapped
class Address:
__tablename__ = "address"
id = mapped_column(Integer, primary_key=True)
user_id = mapped_column(ForeignKey("user.id"))
email_address: Mapped[str]
user: Mapped["User"] = relationship(back_populates="addresses")
上記のスタイルを使用する場合、特定のクラスのマッピングは、デコレータがそのクラスに直接適用された場合に のみ 進行します。継承マッピング( Mapping Class Inheritance Hierarchies で詳細に説明されています)の場合、デコレータはマッピングされる各サブクラスに適用される必要があります:
from sqlalchemy.orm import registry
mapper_registry = registry()
@mapper_registry.mapped
class Person:
__tablename__ = "person"
person_id = mapped_column(Integer, primary_key=True)
type = mapped_column(String, nullable=False)
__mapper_args__ = {
"polymorphic_on": type,
"polymorphic_identity": "person",
}
@mapper_registry.mapped
class Employee(Person):
__tablename__ = "employee"
person_id = mapped_column(ForeignKey("person.person_id"), primary_key=True)
__mapper_args__ = {
"polymorphic_identity": "employee",
}
declarative table と imperative table の両方のテーブル設定スタイルは、宣言型マッピングの宣言型ベースまたはデコレータスタイルのいずれかと一緒に使用できます。
デコレータ形式のマッピングは、SQLAlchemy宣言マッピングを dataclasses や attrs などの他のクラス・インストルメンテーション・システムと組み合わせる場合に便利です。ただし、SQLAlchemy 2.0では、宣言ベース・クラスとのデータクラスの統合も機能するようになりました。