]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
use Column for legacy dataclasses mapping
authorMike Bayer <mike_mp@zzzcomputing.com>
Fri, 24 Feb 2023 04:52:31 +0000 (23:52 -0500)
committerMike Bayer <mike_mp@zzzcomputing.com>
Fri, 24 Feb 2023 04:52:31 +0000 (23:52 -0500)
Fixes: #9361
Change-Id: I9c433960664aa2b75cd03925d9dcf2e1ff27d8ce

doc/build/orm/dataclasses.rst

index 4bb74cbb221eac241b81a7f4ce8ba530a6f3e420..254959ab6c67efd3f1e1dc7faf5700b8ed75bb62 100644 (file)
@@ -521,22 +521,16 @@ both for mapped classes as well as mixins that extend from
 
 .. _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
@@ -572,8 +566,8 @@ for all the other methods that dataclasses generates such as
 
 .. _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
@@ -650,14 +644,18 @@ approach is in the next example.
 
 .. _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
@@ -686,12 +684,10 @@ association::
         __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")}
         )
@@ -702,18 +698,14 @@ association::
     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
@@ -724,7 +716,7 @@ example at :ref:`orm_declarative_mixins_relationships`::
     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):
@@ -742,9 +734,7 @@ came from a mixin that is itself a dataclass, the form would be::
 
         __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")}
@@ -755,13 +745,11 @@ came from a mixin that is itself a dataclass, the form would be::
     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
@@ -782,8 +770,8 @@ came from a mixin that is itself a dataclass, the form would be::
 
 .. _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