SqlAlchemy 2.0 中文文档(四十二)(3)

本文涉及的产品
云原生数据库 PolarDB MySQL 版,通用型 2核4GB 50GB
云原生数据库 PolarDB PostgreSQL 版,标准版 2核4GB 50GB
简介: SqlAlchemy 2.0 中文文档(四十二)

SqlAlchemy 2.0 中文文档(四十二)(2)https://developer.aliyun.com/article/1563013


增强现有类型

TypeDecorator 允许创建自定义类型,将绑定参数和结果处理行为添加到现有类型对象中。当需要额外的在 Python 中对数据进行数据库内/外编组时使用。

注意

TypeDecorator 的绑定和结果处理除了已由托管类型执行的处理外,还由 SQLAlchemy 基于每个 DBAPI 进行自定义,以执行特定于该 DBAPI 的处理。虽然可能通过直接子类化替换给定类型的此处理,但在实践中从不需要,并且 SQLAlchemy 不再支持此作为公共用例。

对象名称 描述
TypeDecorator 允许创建将额外功能添加到现有类型的类型。
class sqlalchemy.types.TypeDecorator

允许创建将额外功能添加到现有类型的类型。

与直接子类化 SQLAlchemy 的内置类型相比,此方法更受欢迎,因为它确保了底层类型的所有必需功能都得到保留。

典型用法:

import sqlalchemy.types as types
class MyType(types.TypeDecorator):
  '''Prefixes Unicode values with "PREFIX:" on the way in and
 strips it off on the way out.
 '''
    impl = types.Unicode
    cache_ok = True
    def process_bind_param(self, value, dialect):
        return "PREFIX:" + value
    def process_result_value(self, value, dialect):
        return value[7:]
    def copy(self, **kw):
        return MyType(self.impl.length)

类级别的 impl 属性是必需的,并且可以引用任何 TypeEngine 类。或者,可以使用 load_dialect_impl() 方法来基于给定的方言提供不同的类型类;在这种情况下,impl 变量可以引用 TypeEngine 作为占位符。

TypeDecorator.cache_ok 类级别的标志指示此自定义 TypeDecorator 是否安全用于作为缓存键的一部分。此标志默认为 None,在 SQL 编译器尝试为使用此类型的语句生成缓存键时,将最初生成警告。如果不能保证每次生成的绑定/结果行为和 SQL 生成都相同,则应将此标志设置为 False;否则,如果该类每次都产生相同的行为,则可以将其设置为 True。有关此功能的更多说明,请参阅 TypeDecorator.cache_ok

接收 Python 类型而不是与最终使用的类型相似的 Python 类型的类型可能希望定义TypeDecorator.coerce_compared_value()方法。这用于在表达式中将 Python 对象强制转换为绑定参数时为表达式系统提供提示。考虑以下表达式:

mytable.c.somecol + datetime.date(2009, 5, 15)

如果“somecol”是一个Integer变体,我们进行日期算术操作是有道理的,其中上面通常被数据库解释为将一定数量的天数添加到给定日期。表达式系统通过不尝试将“date()`”值强制转换为整数导向绑定参数来实现正确的操作。

然而,在TypeDecorator的情况下,我们通常将传入的 Python 类型更改为新的类型 - TypeDecorator默认会“强制”非类型化的一侧成为与其自身相同的类型。例如,我们定义了一个将日期值存储为整数的“epoch”类型如下:

class MyEpochType(types.TypeDecorator):
    impl = types.Integer
    cache_ok = True
    epoch = datetime.date(1970, 1, 1)
    def process_bind_param(self, value, dialect):
        return (value - self.epoch).days
    def process_result_value(self, value, dialect):
        return self.epoch + timedelta(days=value)

我们的表达式somecol + date将使用上述类型将右侧的“date”强制转换为MyEpochType

此行为可以通过TypeDecorator.coerce_compared_value()方法进行覆盖,该方法返回应该用于表达式值的类型。以下我们设置它,以使整数值将被视为Integer,并且任何其他值都被假定为日期并将被视为MyEpochType

def coerce_compared_value(self, op, value):
    if isinstance(value, int):
        return Integer()
    else:
        return self

警告

请注意,coerce_compared_value 的行为默认不会从基本类型那里继承。如果TypeDecorator是用于增强某种类型,以便针对某些类型的运算符执行特殊逻辑,那么必须重写此方法。一个关键示例是装饰JSONJSONB类型; 应使用TypeEngine.coerce_compared_value()的默认规则来处理诸如索引操作之类的运算符:

from sqlalchemy import JSON
from sqlalchemy import TypeDecorator
class MyJsonType(TypeDecorator):
    impl = JSON
    cache_ok = True
    def coerce_compared_value(self, op, value):
        return self.impl.coerce_compared_value(op, value)

如果没有上述步骤,诸如mycol['foo']的索引操作将导致索引值'foo'被 JSON 编码。

类似地,在使用ARRAY数据类型时,索引操作(例如mycol[5])的类型强制转换也由TypeDecorator.coerce_compared_value()处理,除非需要特定操作符的特殊规则,否则简单的重写就足够了:

from sqlalchemy import ARRAY
from sqlalchemy import TypeDecorator
class MyArrayType(TypeDecorator):
    impl = ARRAY
    cache_ok = True
    def coerce_compared_value(self, op, value):
        return self.impl.coerce_compared_value(op, value)

成员

cache_ok, operate(), reverse_operate(), init(),  bind_expression(), bind_processor(), coerce_compared_value(),  coerce_to_is_types, column_expression(), comparator_factory,  compare_values(), copy(), get_dbapi_type(), literal_processor(),  load_dialect_impl(), process_bind_param(), process_literal_param(),  process_result_value(), result_processor(), sort_key_function,  type_engine()

类签名

sqlalchemy.types.TypeDecorator (sqlalchemy.sql.expression.SchemaEventTarget, sqlalchemy.types.ExternalType, sqlalchemy.types.TypeEngine)

attribute cache_ok: bool | None = None

继承自 ExternalType.cache_ok 属性的 ExternalType

表明使用此ExternalType的语句是否“可以缓存”。

默认值None将发出警告,然后不允许缓存包含此类型的语句。将其设置为False以禁用包含此类型的语句的缓存,而无需警告。当设置为True时,对象的类和其状态中选择的元素将用作缓存键的一部分。例如,使用TypeDecorator:

class MyType(TypeDecorator):
    impl = String
    cache_ok = True
    def __init__(self, choices):
        self.choices = tuple(choices)
        self.internal_only = True

上述类型的缓存键将等同于:

>>> MyType(["a", "b", "c"])._static_cache_key
(<class '__main__.MyType'>, ('choices', ('a', 'b', 'c')))

缓存方案将从类型中提取与__init__()方法中参数名称对应的属性。以上,“choices”属性成为缓存键的一部分,但“internal_only”不会,因为没有名为“internal_only”的参数。

可缓存元素的要求是它们是可哈希的,并且还表明对于给定缓存值,每次使用此类型的表达式呈现相同的 SQL。

为了适应引用不可哈希结构(如字典、集合和列表)的数据类型,这些对象可以通过将可哈希结构分配给与参数名称对应的属性来“可缓存”。例如,一个接受查找值字典的数据类型可以将其公开为一系列排序后的元组。给定先前不可缓存的类型:

class LookupType(UserDefinedType):
  '''a custom type that accepts a dictionary as a parameter.
 this is the non-cacheable version, as "self.lookup" is not
 hashable.
 '''
    def __init__(self, lookup):
        self.lookup = lookup
    def get_col_spec(self, **kw):
        return "VARCHAR(255)"
    def bind_processor(self, dialect):
        # ...  works with "self.lookup" ...

其中“lookup”是一个字典。该类型将无法生成缓存键:

>>> type_ = LookupType({"a": 10, "b": 20})
>>> type_._static_cache_key
<stdin>:1: SAWarning: UserDefinedType LookupType({'a': 10, 'b': 20}) will not
produce a cache key because the ``cache_ok`` flag is not set to True.
Set this flag to True if this type object's state is safe to use
in a cache key, or False to disable this warning.
symbol('no_cache')

如果我们确实设置了这样一个缓存键,它将无法使用。我们将得到一个包含其中一个字典的元组结构,这个字典本身不能作为“缓存字典”中的键,比如 SQLAlchemy 的语句缓存,因为 Python 字典不可哈希:

>>> # set cache_ok = True
>>> type_.cache_ok = True
>>> # this is the cache key it would generate
>>> key = type_._static_cache_key
>>> key
(<class '__main__.LookupType'>, ('lookup', {'a': 10, 'b': 20}))
>>> # however this key is not hashable, will fail when used with
>>> # SQLAlchemy statement cache
>>> some_cache = {key: "some sql value"}
Traceback (most recent call last): File "<stdin>", line 1,
in <module> TypeError: unhashable type: 'dict'

可通过将排序后的元组分配给“.lookup”属性来使类型可缓存:

class LookupType(UserDefinedType):
  '''a custom type that accepts a dictionary as a parameter.
 The dictionary is stored both as itself in a private variable,
 and published in a public variable as a sorted tuple of tuples,
 which is hashable and will also return the same value for any
 two equivalent dictionaries.  Note it assumes the keys and
 values of the dictionary are themselves hashable.
 '''
    cache_ok = True
    def __init__(self, lookup):
        self._lookup = lookup
        # assume keys/values of "lookup" are hashable; otherwise
        # they would also need to be converted in some way here
        self.lookup = tuple(
            (key, lookup[key]) for key in sorted(lookup)
        )
    def get_col_spec(self, **kw):
        return "VARCHAR(255)"
    def bind_processor(self, dialect):
        # ...  works with "self._lookup" ...

在上面的例子中,LookupType({"a": 10, "b": 20})的缓存键将是:

>>> LookupType({"a": 10, "b": 20})._static_cache_key
(<class '__main__.LookupType'>, ('lookup', (('a', 10), ('b', 20))))

1.4.14 版本中新增:- 添加了cache_ok标志,以允许对TypeDecorator类的缓存进行一些可配置性。

1.4.28 版本中新增:- 添加了ExternalType mixin,将cache_ok标志泛化到TypeDecoratorUserDefinedType类中。

另请参阅

SQL 编译缓存

class Comparator

一个专门针对TypeDecoratorComparator

通常不需要修改用户定义的TypeDecorator类。

类签名

sqlalchemy.types.TypeDecorator.Comparator (sqlalchemy.types.Comparator)

method operate(op: OperatorType, *other: Any, **kwargs: Any) → ColumnElement[_CT]

对参数进行操作。

这是操作的最低级别,默认情况下引发NotImplementedError

在子类中覆盖这一点可以让所有操作应用通用行为。例如,覆盖ColumnOperators以将func.lower()应用于左侧和右侧:

class MyComparator(ColumnOperators):
    def operate(self, op, other, **kwargs):
        return op(func.lower(self), func.lower(other), **kwargs)

参数:

  • op – 运算符可调用。
  • *other – 操作的‘其他’一侧。对于大多数操作,将是一个单一标量。
  • **kwargs – 修改器。这些可能会被特殊运算符(例如 ColumnOperators.contains())传递。
method reverse_operate(op: OperatorType, other: Any, **kwargs: Any) → ColumnElement[_CT]

对参数执行反向操作。

使用方式与 operate() 相同。

method __init__(*args: Any, **kwargs: Any)

构造一个 TypeDecorator

发送到此处的参数将传递给分配给 impl 类级别属性的类的构造函数,假设 impl 是可调用的,并且生成的对象将被分配给 self.impl 实例属性(因此覆盖了同名的类属性)。

如果类级别的 impl 不是可调用的(不寻常的情况),它将被分配给相同的实例属性‘原样’,忽略传递给构造函数的那些参数。

子类可以重写此方法以完全自定义 self.impl 的生成。

method bind_expression(bindparam: BindParameter[_T]) → ColumnElement[_T] | None

给定一个绑定值(即一个 BindParameter 实例),返回一个 SQL 表达式,通常会包装给定的参数。

注意

在语句的 SQL 编译 阶段调用此方法,当渲染 SQL 字符串时。它不一定针对特定值调用,并且不应与 TypeDecorator.process_bind_param() 方法混淆,后者是处理语句执行时传递给特定参数的实际值的更典型方法。

TypeDecorator 的子类可以重写此方法以为类型提供自定义绑定表达式行为。此实现将替换底层实现类型的实现。

method bind_processor(dialect: Dialect) → _BindProcessorType[_T] | None

为给定 Dialect 提供一个绑定值处理函数。

这是执行绑定值转换的方法,通常通过 TypeEngine.bind_processor() 方法在 SQL 编译 阶段的语句中发生。

注意

TypeDecorator 的用户定义子类不应该实现这个方法,而应该实现 TypeDecorator.process_bind_param() 方法,以保持实现类型提供的“内部”处理。

参数:

dialect – 正在使用的 Dialect 实例。

method coerce_compared_value(op: OperatorType | None, value: Any) → Any

为表达式中的‘强制’Python 值建议一种类型。

默认情况下,返回 self。 当此类型的对象位于尚未分配 SQLAlchemy 类型的纯 Python 对象的表达式的左侧或右侧时,表达式系统会调用此方法:

expr = table.c.somecolumn + 35

在上述情况中,如果somecolumn使用了这种类型,则将使用值operator.add35调用此方法。 返回值是应该用于此特定操作的35的任何 SQLAlchemy 类型。

attribute coerce_to_is_types: Sequence[Type[Any]] = (<class 'NoneType'>,)

指定那些应该在表达式级别上被强制转换为“IS ”的 Python 类型,当使用==进行比较时(与!=结合使用时同样适用于IS NOT)。

对于大多数 SQLAlchemy 类型,这包括NoneType,以及bool

TypeDecorator修改此列表以仅包括NoneType,因为处理布尔类型的类型装饰器实现很常见。

自定义TypeDecorator类可以重写此属性以返回一个空元组,在这种情况下,不会将任何值强制转换为常量。

method column_expression(column: ColumnElement[_T]) → ColumnElement[_T] | None

给定 SELECT 列表达式,返回包装的 SQL 表达式。

注意

此方法在语句的SQL 编译阶段调用,用于呈现 SQL 字符串。 它不会针对特定值调用,并且不应与TypeDecorator.process_result_value()方法混淆,后者是处理在语句执行后返回的结果行中实际值的更典型方法。

TypeDecorator的子类可以重写此方法以为该类型提供自定义列表达式行为。 该实现将替换底层实现类型的实现。

有关方法使用的完整描述,请参阅TypeEngine.column_expression()的描述。

attribute comparator_factory: _ComparatorFactory[Any]

一个Comparator类,将应用于由拥有的操作ColumnElement对象执行。

当在列和 SQL 表达式操作时,核心表达式系统会查询comparator_factory属性。当与此属性关联的Comparator类时,它允许自定义重新定义所有现有运算符,以及定义新的运算符。现有运算符包括通过 Python 运算符重载提供的ColumnOperators.__add__()ColumnOperators.__eq__(),以及由ColumnOperators的标准属性提供的运算符,如ColumnOperators.like()ColumnOperators.in_()

通过简单地对现有类型进行子类化或者使用TypeDecorator,可以允许对此钩子进行基本用法。请参阅文档部分 Redefining and Creating New Operators 以获取示例。

method compare_values(x: Any, y: Any) → bool

给定两个值,比较它们是否相等。

默认情况下,这会调用底层“impl”的TypeEngine.compare_values(),该方法通常使用 Python 的等于运算符==

此函数由 ORM 用于比较原始加载的值与拦截的“更改”值,以确定是否发生了净变化。

method copy(**kw: Any) → Self

生成此TypeDecorator实例的副本。

这是一个浅拷贝,并提供了TypeEngine合同的部分。除非用户定义的TypeDecorator具有应该被深度复制的本地状态,否则通常不需要重写它。

method get_dbapi_type(dbapi: module) → Any | None

返回由此TypeDecorator表示的 DBAPI 类型对象。

默认情况下,这会调用底层“impl”的TypeEngine.get_dbapi_type()

method literal_processor(dialect: Dialect) → _LiteralProcessorType[_T] | None

为给定的Dialect提供一个字面值处理函数。

这是实现通常通过TypeEngine.literal_processor()方法进行的字面值转换的TypeEngine合同的方法。

注意

用户定义的TypeDecorator子类不应该实现这个方法,而应该实现TypeDecorator.process_literal_param(),以便保持实现类型提供的“内部”处理。

method load_dialect_impl(dialect: Dialect) → TypeEngine[Any]

返回对应于方言的TypeEngine对象。

这是一个最终用户覆盖的钩子,可用于根据给定的方言提供不同的类型。它由TypeDecoratortype_engine()实现使用,以帮助确定对于给定的TypeDecorator最终应该返回什么类型。

默认情况下返回self.impl

method process_bind_param(value: _T | None, dialect: Dialect) → Any

接收要转换的绑定参数值。

自定义的TypeDecorator子类应该重写此方法,以提供传入数据值的自定义行为。此方法在语句执行时间调用,并传递要与语句中的绑定参数相关联的字面 Python 数据值。

操作可以是任何想要执行自定义行为的内容,比如转换或序列化数据。这也可以用作验证逻辑的钩子。

参数:

  • value – 要操作的数据,由子类中此方法期望的任何类型。可以是None
  • dialect – 正在使用的Dialect

另请参阅

扩展现有类型

TypeDecorator.process_result_value()

method process_literal_param(value: _T | None, dialect: Dialect) → str

接收要在语句中内联呈现的字面参数值。

注意

在语句的SQL 编译阶段调用此方法,当呈现 SQL 字符串时。与其他 SQL 编译方法不同,它会传递一个具体的 Python 值,以字符串形式呈现。但是,它不应与TypeDecorator.process_bind_param()方法混淆,后者是处理在语句执行时传递给特定参数的实际值的更典型方法。

自定义的TypeDecorator子类应该重写这个方法,以提供特定情况下的自定义行为,用于处理作为字面值呈现的传入数据值。

返回的字符串将呈现到输出字符串中。

method process_result_value(value: Any | None, dialect: Dialect) → _T | None

接收要转换的结果行列值。

自定义的TypeDecorator子类应重写此方法,以提供从数据库返回的结果行中接收的数据值的自定义行为。此方法在结果获取时间调用,并传递从数据库结果行中提取的字面 Python 数据值。

操作可以是任何所需的自定义行为,例如转换或反序列化数据。

参数:

  • value – 要操作的数据,子类中此方法所期望的任何类型的数据。可以为None
  • dialect – 正在使用的Dialect

另请参阅

增强现有类型

TypeDecorator.process_bind_param()

method result_processor(dialect: Dialect, coltype: Any) → _ResultProcessorType[_T] | None

为给定的Dialect提供结果值处理函数。

这是满足绑定值转换的TypeEngine契约的方法,通常通过TypeEngine.result_processor()方法进行。

注意

用户定义的TypeDecorator子类不应实现此方法,而应该实现TypeDecorator.process_result_value(),以便维护实现类型提供的“内部”处理。

参数:

  • dialect – 正在使用的方言实例。
  • coltype – 一个 SQLAlchemy 数据类型。
attribute sort_key_function: Callable[[Any], Any] | None

一个可作为排序关键字传递给sorted的排序函数。

None的默认值表示此类型存储的值是自排序的。

版本 1.3.8 中新增。

method type_engine(dialect: Dialect) → TypeEngine[Any]

为此TypeDecorator返回一个特定于方言的TypeEngine实例。

在大多数情况下,此方法返回由self.impl表示的TypeEngine类型的方言适配形式。使用dialect_impl()。可以通过重写load_dialect_impl()来在此处自定义行为。

TypeDecorator 示例

以下是一些关键的TypeDecorator示例。

将编码字符串强制转换为 Unicode

Unicode 类型常见的一个令人困惑的地方是,它仅在 Python 一侧处理 Python unicode 对象,这意味着作为绑定参数传递给它的值必须是 u'some string' 的形式,如果使用的是 Python 2 而不是 3。它执行的编码/解码函数仅适合于所使用的 DBAPI 所需,并且主要是一个私有的实现细节。

通过使用 TypeDecorator ,可以实现安全接收 Python 字节串的类型的用例,即包含非 ASCII 字符并且在 Python 2 中不是 u'' 对象的字符串,必要时进行强制转换:

from sqlalchemy.types import TypeDecorator, Unicode
class CoerceUTF8(TypeDecorator):
  """Safely coerce Python bytestrings to Unicode
 before passing off to the database."""
    impl = Unicode
    def process_bind_param(self, value, dialect):
        if isinstance(value, str):
            value = value.decode("utf-8")
        return value

数字四舍五入

一些数据库连接器(如 SQL Server 的连接器)如果传递的 Decimal 有太多的小数位数,会出现问题。以下是将其四舍五入的方法:

from sqlalchemy.types import TypeDecorator, Numeric
from decimal import Decimal
class SafeNumeric(TypeDecorator):
  """Adds quantization to Numeric."""
    impl = Numeric
    def __init__(self, *arg, **kw):
        TypeDecorator.__init__(self, *arg, **kw)
        self.quantize_int = -self.impl.scale
        self.quantize = Decimal(10) ** self.quantize_int
    def process_bind_param(self, value, dialect):
        if isinstance(value, Decimal) and value.as_tuple()[2] < self.quantize_int:
            value = value.quantize(self.quantize)
        return value

将时区感知时间戳存储为时区无关的 UTC

数据库中的时间戳应始终以与时区无关的方式存储。对于大多数数据库来说,这意味着确保时间戳首先处于 UTC  时区,然后将其存储为时区无关的(即,没有与之关联的任何时区;UTC 被假定为“隐式”时区)。另外,通常首选数据库特定类型,如  PostgreSQL 的 “TIMESTAMP WITH TIMEZONE” ,因为其功能更丰富;但是,存储为纯 UTC  将在所有数据库和驱动程序上工作。当时区智能数据库类型不是一个选择或不被首选时,可以使用 TypeDecorator 创建一个将时区感知时间戳转换为时区无关的数据类型,并反之亦然。下面,Python 的内置 datetime.timezone.utc 时区用于标准化和非标准化:

import datetime
class TZDateTime(TypeDecorator):
    impl = DateTime
    cache_ok = True
    def process_bind_param(self, value, dialect):
        if value is not None:
            if not value.tzinfo or value.tzinfo.utcoffset(value) is None:
                raise TypeError("tzinfo is required")
            value = value.astimezone(datetime.timezone.utc).replace(tzinfo=None)
        return value
    def process_result_value(self, value, dialect):
        if value is not None:
            value = value.replace(tzinfo=datetime.timezone.utc)
        return value

与后端无关的 GUID 类型

注意

自版本 2.0 起,内置的 Uuid 类型行为类似应该优先考虑。这个示例只是一个接收并返回 Python 对象的类型装饰器的示例。

接收和返回 Python 的 uuid() 对象。在使用 PostgreSQL 时使用 PG UUID 类型,在使用 MSSQL 时使用 UNIQUEIDENTIFIER,在其他后端使用 CHAR(32),以字符串格式存储。GUIDHyphens 版本使用带连字符的方式存储值,而不仅仅是十六进制字符串,使用 CHAR(36) 类型:

from operator import attrgetter
from sqlalchemy.types import TypeDecorator, CHAR
from sqlalchemy.dialects.mssql import UNIQUEIDENTIFIER
from sqlalchemy.dialects.postgresql import UUID
import uuid
class GUID(TypeDecorator):
  """Platform-independent GUID type.
 Uses PostgreSQL's UUID type or MSSQL's UNIQUEIDENTIFIER,
 otherwise uses CHAR(32), storing as stringified hex values.
 """
    impl = CHAR
    cache_ok = True
    _default_type = CHAR(32)
    _uuid_as_str = attrgetter("hex")
    def load_dialect_impl(self, dialect):
        if dialect.name == "postgresql":
            return dialect.type_descriptor(UUID())
        elif dialect.name == "mssql":
            return dialect.type_descriptor(UNIQUEIDENTIFIER())
        else:
            return dialect.type_descriptor(self._default_type)
    def process_bind_param(self, value, dialect):
        if value is None or dialect.name in ("postgresql", "mssql"):
            return value
        else:
            if not isinstance(value, uuid.UUID):
                value = uuid.UUID(value)
            return self._uuid_as_str(value)
    def process_result_value(self, value, dialect):
        if value is None:
            return value
        else:
            if not isinstance(value, uuid.UUID):
                value = uuid.UUID(value)
            return value
class GUIDHyphens(GUID):
  """Platform-independent GUID type.
 Uses PostgreSQL's UUID type or MSSQL's UNIQUEIDENTIFIER,
 otherwise uses CHAR(36), storing as stringified uuid values.
 """
    _default_type = CHAR(36)
    _uuid_as_str = str
将 Python uuid.UUID 链接到 ORM 映射的自定义类型

当使用 注释的声明性表 进行 ORM 映射时,可以通过将其添加到 类型注释映射 中将上面定义的自定义 GUID 类型与 Python uuid.UUID 数据类型关联起来,该映射通常在 DeclarativeBase 类上定义:

import uuid
from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column
class Base(DeclarativeBase):
    type_annotation_map = {
        uuid.UUID: GUID,
    }

使用上述配置,从 Base 扩展的 ORM 映射类可以在注释中引用 Python uuid.UUID,这将自动使用 GUID

class MyModel(Base):
    __tablename__ = "my_table"
    id: Mapped[uuid.UUID] = mapped_column(primary_key=True)

另请参阅

自定义类型映射


SqlAlchemy 2.0 中文文档(四十二)(4)https://developer.aliyun.com/article/1563015

相关实践学习
使用PolarDB和ECS搭建门户网站
本场景主要介绍基于PolarDB和ECS实现搭建门户网站。
阿里云数据库产品家族及特性
阿里云智能数据库产品团队一直致力于不断健全产品体系,提升产品性能,打磨产品功能,从而帮助客户实现更加极致的弹性能力、具备更强的扩展能力、并利用云设施进一步降低企业成本。以云原生+分布式为核心技术抓手,打造以自研的在线事务型(OLTP)数据库Polar DB和在线分析型(OLAP)数据库Analytic DB为代表的新一代企业级云原生数据库产品体系, 结合NoSQL数据库、数据库生态工具、云原生智能化数据库管控平台,为阿里巴巴经济体以及各个行业的企业客户和开发者提供从公共云到混合云再到私有云的完整解决方案,提供基于云基础设施进行数据从处理、到存储、再到计算与分析的一体化解决方案。本节课带你了解阿里云数据库产品家族及特性。
相关文章
|
3月前
|
SQL JSON 测试技术
SqlAlchemy 2.0 中文文档(七十五)(2)
SqlAlchemy 2.0 中文文档(七十五)
38 3
|
3月前
|
SQL JSON 关系型数据库
SqlAlchemy 2.0 中文文档(七十五)(1)
SqlAlchemy 2.0 中文文档(七十五)
62 4
|
3月前
|
SQL 数据库连接 Linux
SqlAlchemy 2.0 中文文档(五十二)(4)
SqlAlchemy 2.0 中文文档(五十二)
40 0
|
3月前
|
SQL 测试技术 数据库
SqlAlchemy 2.0 中文文档(五十二)(1)
SqlAlchemy 2.0 中文文档(五十二)
22 0
|
3月前
|
SQL NoSQL 数据库
SqlAlchemy 2.0 中文文档(五十二)(5)
SqlAlchemy 2.0 中文文档(五十二)
21 0
|
3月前
|
SQL JSON 数据库
SqlAlchemy 2.0 中文文档(五十二)(6)
SqlAlchemy 2.0 中文文档(五十二)
17 0
|
3月前
|
SQL 数据库连接 Linux
SqlAlchemy 2.0 中文文档(五十二)(7)
SqlAlchemy 2.0 中文文档(五十二)
42 0
|
3月前
|
SQL JSON 关系型数据库
SqlAlchemy 2.0 中文文档(五十二)(3)
SqlAlchemy 2.0 中文文档(五十二)
26 0
|
3月前
|
SQL NoSQL 数据库
SqlAlchemy 2.0 中文文档(五十二)(2)
SqlAlchemy 2.0 中文文档(五十二)
30 0
|
3月前
|
SQL 缓存 数据库
SqlAlchemy 2.0 中文文档(四十二)(5)
SqlAlchemy 2.0 中文文档(四十二)
26 0