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クラスは、既存の registryregistry という名前のクラス変数として割り当てることによって作成することもできます:

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 クラスは、マップされる新しいクラスのベースとして機能します。上記では、新しいマップされたクラス UserAddress が構築されます。

構築された各サブクラスに対して、クラスの本体は、完全なマッピングを構成する舞台裏で TableMapper オブジェクトの両方を定義する宣言的なマッピング手法に従います。

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 tableimperative table の両方のテーブル設定スタイルは、宣言型マッピングの宣言型ベースまたはデコレータスタイルのいずれかと一緒に使用できます。

デコレータ形式のマッピングは、SQLAlchemy宣言マッピングを dataclassesattrs などの他のクラス・インストルメンテーション・システムと組み合わせる場合に便利です。ただし、SQLAlchemy 2.0では、宣言ベース・クラスとのデータクラスの統合も機能するようになりました。