diff options
| author | mike bayer <mike_mp@zzzcomputing.com> | 2022-11-30 16:35:41 +0000 |
|---|---|---|
| committer | Gerrit Code Review <gerrit@ci3.zzzcomputing.com> | 2022-11-30 16:35:41 +0000 |
| commit | c440c920aecd6593974e5a0d37cdb9069e5d3e57 (patch) | |
| tree | 1ae88befaef5da0bc1e48c8fde5c05e59cbd9dee /doc | |
| parent | 1057b47bca2522e45d9621a709d033aa4fb88888 (diff) | |
| parent | 9c9fd31bcea3beaed6d14fde639e65f6b43bea09 (diff) | |
| download | sqlalchemy-c440c920aecd6593974e5a0d37cdb9069e5d3e57.tar.gz | |
Merge "Improve support for enum in mapped classes" into main
Diffstat (limited to 'doc')
| -rw-r--r-- | doc/build/changelog/unreleased_20/8859.rst | 16 | ||||
| -rw-r--r-- | doc/build/orm/declarative_tables.rst | 100 |
2 files changed, 116 insertions, 0 deletions
diff --git a/doc/build/changelog/unreleased_20/8859.rst b/doc/build/changelog/unreleased_20/8859.rst new file mode 100644 index 000000000..85e4be422 --- /dev/null +++ b/doc/build/changelog/unreleased_20/8859.rst @@ -0,0 +1,16 @@ +.. change:: + :tags: usecase, orm + :tickets: 8859 + + Added support custom user-defined types which extend the Python + ``enum.Enum`` base class to be resolved automatically + to SQLAlchemy :class:`.Enum` SQL types, when using the Annotated + Declarative Table feature. The feature is made possible through new + lookup features added to the ORM type map feature, and includes support + for changing the arguments of the :class:`.Enum` that's generated by + default as well as setting up specific ``enum.Enum`` types within + the map with specific arguments. + + .. seealso:: + + :ref:`orm_declarative_mapped_column_enums` diff --git a/doc/build/orm/declarative_tables.rst b/doc/build/orm/declarative_tables.rst index 475813f81..806a6897f 100644 --- a/doc/build/orm/declarative_tables.rst +++ b/doc/build/orm/declarative_tables.rst @@ -369,6 +369,106 @@ while still being able to use succinct annotation-only :func:`_orm.mapped_column configurations. There are two more levels of Python-type configurability available beyond this, described in the next two sections. +.. _orm_declarative_mapped_column_enums: + +Using Python ``Enum`` types in the type map +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. versionadded:: 2.0.0b4 + +User-defined Python types which derive from the Python built-in ``enum.Enum`` +class are automatically linked to the SQLAlchemy :class:`.Enum` datatype +when used in an ORM declarative mapping:: + + import enum + + from sqlalchemy.orm import DeclarativeBase + from sqlalchemy.orm import Mapped + from sqlalchemy.orm import mapped_column + + + class Base(DeclarativeBase): + pass + + + class Status(enum.Enum): + PENDING = "pending" + RECEIVED = "received" + COMPLETED = "completed" + + + class SomeClass(Base): + __tablename__ = "some_table" + + id: Mapped[int] = mapped_column(primary_key=True) + status: Mapped[Status] + +In the above example, the mapped attribute ``SomeClass.status`` will be +linked to a :class:`.Column` with the datatype of ``Enum(Status)``. +We can see this for example in the CREATE TABLE output for the PostgreSQL +database: + +.. sourcecode:: sql + + CREATE TYPE status AS ENUM ('PENDING', 'RECEIVED', 'COMPLETED') + + CREATE TABLE some_table ( + id SERIAL NOT NULL, + status status NOT NULL, + PRIMARY KEY (id) + ) + +The entry used in :paramref:`_orm.registry.type_annotation_map` links the +base ``enum.Enum`` Python type to the SQLAlchemy :class:`.Enum` SQL +type, using a special form which indicates to the :class:`.Enum` datatype +that it should automatically configure itself against an arbitrary enumerated +type. This configuration, which is implicit by default, would be indicated +explicitly as:: + + import enum + import sqlalchemy + + + class Base(DeclarativeBase): + type_annotation_map = {enum.Enum: sqlalchemy.Enum(enum.Enum)} + +The resolution logic within Declarative is able to resolve subclasses +of ``enum.Enum``, in the above example the custom ``Status`` enumeration, +to match the ``enum.Enum`` entry in the +:paramref:`_orm.registry.type_annotation_map` dictionary. The :class:`.Enum` +SQL type then knows how to produce a configured version of itself with the +appropriate settings, including default string length. + +In order to modify the configuration of the :class:`.enum.Enum` datatype used +in this mapping, use the above form, indicating additional arguments. For +example, to use "non native enumerations" on all backends, the +:paramref:`.Enum.native_enum` parameter may be set to False for all types:: + + import enum + import sqlalchemy + + + class Base(DeclarativeBase): + type_annotation_map = {enum.Enum: sqlalchemy.Enum(enum.Enum, native_enum=False)} + +To use a specific configuration for a specific ``enum.Enum`` subtype, such +as setting the string length to 50 when using the example ``Status`` +datatype:: + + import enum + import sqlalchemy + + + class Status(enum.Enum): + PENDING = "pending" + RECEIVED = "received" + COMPLETED = "completed" + + + class Base(DeclarativeBase): + type_annotation_map = { + Status: sqlalchemy.Enum(Status, length=50, native_enum=False) + } .. _orm_declarative_mapped_column_type_map_pep593: |
