diff options
| author | Federico Caselli <cfederico87@gmail.com> | 2022-11-27 18:11:34 +0100 |
|---|---|---|
| committer | Mike Bayer <mike_mp@zzzcomputing.com> | 2022-11-29 17:49:27 -0500 |
| commit | 9c9fd31bcea3beaed6d14fde639e65f6b43bea09 (patch) | |
| tree | 2eef4b31c1f89f364c9bf15fdf153a4aad0f98c6 /doc | |
| parent | 78833af4e650d37e6257cfbb541e4db56e2a285f (diff) | |
| download | sqlalchemy-9c9fd31bcea3beaed6d14fde639e65f6b43bea09.tar.gz | |
Improve support for enum in mapped classes
Add a new system by which TypeEngine objects have some
say in how the declarative type registry interprets them.
The Enum datatype is the primary target for this but it is
hoped the system may be useful for other types as well.
Fixes: #8859
Change-Id: I15ac3daee770408b5795746f47c1bbd931b7d26d
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: |
