.. _orm_declarative_dataclasses:
-Applying ORM Mappings to an existing dataclass
-----------------------------------------------
+Applying ORM Mappings to an existing dataclass (legacy dataclass use)
+---------------------------------------------------------------------
-SQLAlchemy's :ref:`native dataclass <orm_declarative_native_dataclasses>`
-support builds upon the previous version of the feature first introduced in
-SQLAlchemy 1.4, which supports the application of ORM mappings to a class after
-it has been processed with the ``@dataclass`` decorator, by using either the
-:meth:`_orm.registry.mapped` class decorator, or the
-:meth:`_orm.registry.map_imperatively` method to apply ORM mappings to the
-class using Imperative. This approach is still viable for applications that are
-using partially or fully imperative mapping forms with dataclasses.
+.. legacy::
-For fully Declarative mapping combined with dataclasses, the
-:ref:`orm_declarative_native_dataclasses` approach should be preferred.
-
-.. versionadded:: 1.4 Added support for direct mapping of Python dataclasses
+ The approaches described here are superseded by
+ the :ref:`orm_declarative_native_dataclasses` feature new in the 2.0
+ series of SQLAlchemy. This newer version of the feature builds upon
+ the dataclass support first added in version 1.4, which is described
+ in this section.
To map an existing dataclass, SQLAlchemy's "inline" declarative directives
cannot be used directly; ORM directives are assigned using one of three
.. _orm_declarative_dataclasses_imperative_table:
-Mapping dataclasses using Declarative With Imperative Table
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+Mapping pre-existing dataclasses using Declarative With Imperative Table
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
An example of a mapping using ``@dataclass`` using
:ref:`orm_imperative_table_configuration` is below. A complete
.. _orm_declarative_dataclasses_declarative_table:
-Mapping dataclasses using Declarative Mapping
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+Mapping pre-existing dataclasses using Declarative-style fields
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-.. deprecated:: 2.0 This approach to Declarative mapping with
+.. legacy:: This approach to Declarative mapping with
dataclasses should be considered as legacy. It will remain supported
however is unlikely to offer any advantages against the new
approach detailed at :ref:`orm_declarative_native_dataclasses`.
+ Note that **mapped_column() is not supported with this use**;
+ the :class:`_schema.Column` construct should continue to be used to declare
+ table metadata within the ``metadata`` field of ``dataclasses.field()``.
+
The fully declarative approach requires that :class:`_schema.Column` objects
are declared as class attributes, which when using dataclasses would conflict
with the dataclass-level attributes. An approach to combine these together
__tablename__ = "user"
__sa_dataclass_metadata_key__ = "sa"
- id: int = field(
- init=False, metadata={"sa": mapped_column(Integer, primary_key=True)}
- )
- name: str = field(default=None, metadata={"sa": mapped_column(String(50))})
- fullname: str = field(default=None, metadata={"sa": mapped_column(String(50))})
- nickname: str = field(default=None, metadata={"sa": mapped_column(String(12))})
+ id: int = field(init=False, metadata={"sa": Column(Integer, primary_key=True)})
+ name: str = field(default=None, metadata={"sa": Column(String(50))})
+ fullname: str = field(default=None, metadata={"sa": Column(String(50))})
+ nickname: str = field(default=None, metadata={"sa": Column(String(12))})
addresses: List[Address] = field(
default_factory=list, metadata={"sa": relationship("Address")}
)
class Address:
__tablename__ = "address"
__sa_dataclass_metadata_key__ = "sa"
- id: int = field(
- init=False, metadata={"sa": mapped_column(Integer, primary_key=True)}
- )
- user_id: int = field(
- init=False, metadata={"sa": mapped_column(ForeignKey("user.id"))}
- )
- email_address: str = field(default=None, metadata={"sa": mapped_column(String(50))})
+ id: int = field(init=False, metadata={"sa": Column(Integer, primary_key=True)})
+ user_id: int = field(init=False, metadata={"sa": Column(ForeignKey("user.id"))})
+ email_address: str = field(default=None, metadata={"sa": Column(String(50))})
.. _orm_declarative_dataclasses_mixin:
-Using Declarative Mixins with Dataclasses
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Using Declarative Mixins with pre-existing dataclasses
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In the section :ref:`orm_mixins_toplevel`, Declarative Mixin classes
are introduced. One requirement of declarative mixins is that certain
class RefTargetMixin:
@declared_attr
def target_id(cls):
- return mapped_column("target_id", ForeignKey("target.id"))
+ return Column("target_id", ForeignKey("target.id"))
@declared_attr
def target(cls):
__sa_dataclass_metadata_key__ = "sa"
- id: int = field(
- init=False, metadata={"sa": mapped_column(Integer, primary_key=True)}
- )
+ id: int = field(init=False, metadata={"sa": Column(Integer, primary_key=True)})
addresses: List[Address] = field(
default_factory=list, metadata={"sa": lambda: relationship("Address")}
class AddressMixin:
__tablename__ = "address"
__sa_dataclass_metadata_key__ = "sa"
- id: int = field(
- init=False, metadata={"sa": mapped_column(Integer, primary_key=True)}
- )
+ id: int = field(init=False, metadata={"sa": Column(Integer, primary_key=True)})
user_id: int = field(
- init=False, metadata={"sa": lambda: mapped_column(ForeignKey("user.id"))}
+ init=False, metadata={"sa": lambda: Column(ForeignKey("user.id"))}
)
- email_address: str = field(default=None, metadata={"sa": mapped_column(String(50))})
+ email_address: str = field(default=None, metadata={"sa": Column(String(50))})
@mapper_registry.mapped
.. _orm_imperative_dataclasses:
-Mapping dataclasses using Imperative Mapping
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+Mapping pre-existing dataclasses using Imperative Mapping
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
As described previously, a class which is set up as a dataclass using the
``@dataclass`` decorator can then be further decorated using the