From: Federico Caselli Date: Mon, 9 Jan 2023 20:45:11 +0000 (+0100) Subject: Make the custom type map more discoverable X-Git-Tag: rel_2_0_0rc3~17 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=b04b7527ed1df22d32707acda9a3c1fea04ca5a8;p=thirdparty%2Fsqlalchemy%2Fsqlalchemy.git Make the custom type map more discoverable Change-Id: Id6cdaddad83aa93508e256e54010a6c53218b717 --- diff --git a/doc/build/core/custom_types.rst b/doc/build/core/custom_types.rst index f46d74f4c7..44187ee4c1 100644 --- a/doc/build/core/custom_types.rst +++ b/doc/build/core/custom_types.rst @@ -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 ` +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 `, +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 ^^^^^^^^^^^^^^^^^^^^ diff --git a/doc/build/orm/declarative_tables.rst b/doc/build/orm/declarative_tables.rst index 882d504ebd..a45fdfd8ed 100644 --- a/doc/build/orm/declarative_tables.rst +++ b/doc/build/orm/declarative_tables.rst @@ -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): diff --git a/doc/build/orm/quickstart.rst b/doc/build/orm/quickstart.rst index a22ad2ffd5..a4531e8d34 100644 --- a/doc/build/orm/quickstart.rst +++ b/doc/build/orm/quickstart.rst @@ -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 `. The :func:`_orm.mapped_column` directive is used for all column-based attributes that require more specific customization. Besides typing diff --git a/doc/build/tutorial/metadata.rst b/doc/build/tutorial/metadata.rst index 65047fd9c3..7e0aa200a5 100644 --- a/doc/build/tutorial/metadata.rst +++ b/doc/build/tutorial/metadata.rst @@ -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 `, so that this same -:class:`_schema.MetaData` is shared among ORM- and Core-declared +ORM-centric :class:`_orm.registry` or +:ref:`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.