]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
Make the custom type map more discoverable
authorFederico Caselli <cfederico87@gmail.com>
Mon, 9 Jan 2023 20:45:11 +0000 (21:45 +0100)
committerMike Bayer <mike_mp@zzzcomputing.com>
Fri, 13 Jan 2023 15:40:19 +0000 (10:40 -0500)
Change-Id: Id6cdaddad83aa93508e256e54010a6c53218b717

doc/build/core/custom_types.rst
doc/build/orm/declarative_tables.rst
doc/build/orm/quickstart.rst
doc/build/tutorial/metadata.rst

index f46d74f4c7d409c61f36eec5b331a053fd65fa68..44187ee4c154af84e6beeae5269cea34bf678733 100644 (file)
@@ -218,6 +218,37 @@ binary in CHAR(16) if desired::
                     value = uuid.UUID(value)
                 return value
 
+Linking Python ``uuid.UUID`` to the Custom Type for ORM mappings
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+When declaring ORM mappings using :ref:`Annotated Declarative Table <orm_declarative_mapped_column>`
+mappings, the custom ``GUID`` type defined above may be associated with
+the Python ``uuid.UUID`` datatype by adding it to the
+:ref:`type annotation map <orm_declarative_mapped_column_type_map>`,
+which is typically defined on the :class:`_orm.DeclarativeBase` class::
+
+    import uuid
+    from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column
+
+
+    class Base(DeclarativeBase):
+        type_annotation_map = {
+            uuid.UUID: GUID,
+        }
+
+With the above configuration, ORM mapped classes which extend from
+``Base`` may refer to Python ``uuid.UUID`` in annotations which will make use
+of ``GUID`` automatically::
+
+    class MyModel(Base):
+        __tablename__ = "my_table"
+
+        id: Mapped[uuid.UUID] = mapped_column(primary_key=True)
+
+.. seealso::
+
+    :ref:`orm_declarative_mapped_column_type_map`
+
 Marshal JSON Strings
 ^^^^^^^^^^^^^^^^^^^^
 
index 882d504ebd0f9277b0f49623d95cd82a6a3927e5..a45fdfd8ed58a5bb136daeabb4a3a91540a88bf8 100644 (file)
@@ -322,13 +322,11 @@ the registry and Declarative base could be configured as::
 
 
     class Base(DeclarativeBase):
-        registry = registry(
-            type_annotation_map={
-                int: BIGINT,
-                datetime.datetime: TIMESTAMP(timezone=True),
-                str: String().with_variant(NVARCHAR, "mssql"),
-            }
-        )
+        type_annotation_map = {
+            int: BIGINT,
+            datetime.datetime: TIMESTAMP(timezone=True),
+            str: String().with_variant(NVARCHAR, "mssql"),
+        }
 
 
     class SomeClass(Base):
index a22ad2ffd548e72fd39f66de6313e0e6c2da1e99..a4531e8d345eb0a56ce4c33a56600e3fdc3d91d2 100644 (file)
@@ -82,7 +82,9 @@ that's associated with each :class:`_orm.Mapped` annotation; ``int`` for
 not the ``Optional[]`` type modifier is used. More specific typing information
 may be indicated using SQLAlchemy type objects in the right side
 :func:`_orm.mapped_column` directive, such as the :class:`.String` datatype
-used above in the ``User.name`` column.
+used above in the ``User.name`` column. The association between Python types
+and SQL types can be customized using the
+:ref:`type annotation map <orm_declarative_mapped_column_type_map>`.
 
 The :func:`_orm.mapped_column` directive is used for all column-based
 attributes that require more specific customization. Besides typing
index 65047fd9c3072d41be7a52abf7bccb8ae40ed1ed..7e0aa200a560a6b7421d9619dcfd35e974b14d1a 100644 (file)
@@ -72,16 +72,19 @@ Having a single :class:`_schema.MetaData` object for an entire application is
 the most common case, represented as a module-level variable in a single place
 in an application, often in a "models" or "dbschema" type of package. It is
 also very common that the :class:`_schema.MetaData` is accessed via an
-ORM-centric registry or base class such as the
-:ref:`Declarative Base <tutorial_orm_declarative_base>`, so that this same
-:class:`_schema.MetaData` is shared among ORM- and Core-declared
+ORM-centric :class:`_orm.registry` or
+:ref:`Declarative Base <tutorial_orm_declarative_base>` base class, so that
+this same :class:`_schema.MetaData` is shared among ORM- and Core-declared
 :class:`_schema.Table` objects.
 
-There can be multiple :class:`_schema.MetaData` collections as well, however
-it's typically most helpful if a series of :class:`_schema.Table` objects that
-are related to each other belong to a single :class:`_schema.MetaData`
-collection.
-
+There can be multiple :class:`_schema.MetaData` collections as well;
+:class:`_schema.Table` objects can to refer to :class:`_schema.Table` objects
+in other collections without restrictions. However, for groups of
+:class:`_schema.Table` objects that are related to each other, it is in
+practice much more straightforward to have them set up within a single
+:class:`_schema.MetaData` collection, both from the perspective of declaring
+them, as well as from the perspective of DDL (i.e. CREATE and DROP) statements
+being emitted in the correct order.
 
 Once we have a :class:`_schema.MetaData` object, we can declare some
 :class:`_schema.Table` objects.  This tutorial will start with the classic
@@ -102,13 +105,17 @@ that will be how we will refer to the table in application code::
     ...     Column("fullname", String),
     ... )
 
+With the above example, when we wish to write code that refers to the
+"user_account" table in the database, we will use the ``user_table``
+Python variable to refer to it.
+
 Components of ``Table``
 ^^^^^^^^^^^^^^^^^^^^^^^
 
-We can observe that the :class:`_schema.Table` construct looks a lot like
-a SQL CREATE TABLE statement; starting with the table name, then listing out
-each column, where each column has a name and a datatype.   The objects we
-use above are:
+We can observe that the :class:`_schema.Table` construct as written in Python
+has a resemblence to a SQL CREATE TABLE statement; starting with the table
+name, then listing out each column, where each column has a name and a
+datatype. The objects we use above are:
 
 * :class:`_schema.Table` - represents a database table and assigns itself
   to a :class:`_schema.MetaData` collection.
@@ -143,7 +150,7 @@ is to generate :term:`DDL` on a particular database connection.  But first
 we will declare a second :class:`_schema.Table`.
 
 Declaring Simple Constraints
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 The first :class:`_schema.Column` in the example ``user_table`` includes the
 :paramref:`_schema.Column.primary_key` parameter which is a shorthand technique
@@ -194,7 +201,7 @@ In the next section we will emit the completed DDL for the ``user`` and
 .. _tutorial_emitting_ddl:
 
 Emitting DDL to the Database
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 We've constructed a an object structure that represents
 two database tables in a database, starting at the root :class:`_schema.MetaData`
@@ -413,8 +420,9 @@ about these classes include:
   :class:`_orm.Mapped` type annotation alone, using simple Python types like
   ``int`` and ``str`` to mean :class:`.Integer` and :class:`.String`.
   Customization of how Python types are interpreted within the Declarative
-  mapping process is very open ended; see the section
-  :ref:`orm_declarative_mapped_column` for background.
+  mapping process is very open ended; see the sections
+  :ref:`orm_declarative_mapped_column` and
+  :ref:`orm_declarative_mapped_column_type_map` for background.
 * A column can be declared as "nullable" or "not null" based on the
   presence of the ``Optional[]`` type annotation; alternatively, the
   :paramref:`_orm.mapped_column.nullable` parameter may be used instead.