自定义类型¶

存在多种方法来重新定义现有类型的行为以及提供新的类型。

重写类型编译

一个常见的需求是强制更改类型的“字符串”版本,即在create table语句或其他SQL函数(如cast)中呈现的版本。例如,应用程序可能希望强制呈现 BINARY 适用于除一个平台外的所有平台 BLOB 待渲染。在本例中,使用现有的泛型类型 LargeBinary ,是大多数用例的首选。但是为了更准确地控制类型,每个方言的编译指令可以与任何类型相关联:

from sqlalchemy.ext.compiler import compiles
from sqlalchemy.types import BINARY

@compiles(BINARY, "sqlite")
def compile_binary_sqlite(type_, compiler, **kw):
    return "BLOB"

上述代码允许使用 types.BINARY ,将生成字符串 BINARY 除了sqlite以外的所有后端,在这种情况下,它将生成 BLOB .

见剖面图 更改类型的编译 ,的一个子部分 自定义SQL构造和编译扩展 ,用于其他示例。

扩充现有类型

这个 TypeDecorator 允许创建自定义类型,将绑定参数和结果处理行为添加到现有类型对象。当需要在python中对数据库之间的数据进行额外的封送处理时,使用它。

注解

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

class sqlalchemy.types.TypeDecorator(*args, **kwargs)

基地: sqlalchemy.sql.expression.SchemaEventTargetsqlalchemy.types.TypeEngine

允许创建向现有类型添加附加功能的类型。

此方法优先于直接对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

    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”属性是必需的,并且可以引用任何类型引擎类。或者,可以使用load_dialect_impl()方法根据给定的方言提供不同的类型类;在这种情况下,“impl”变量可以引用 TypeEngine 作为占位符。

接收与使用的最终类型不同的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

    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 如果使用上述类型,则右侧的“日期”也将被视为 MyEpochType .

此行为可以通过 coerce_compared_value() 方法,返回应用于表达式值的类型。下面我们将其设置为一个整数值将被视为 Integer ,任何其他值假定为日期,并将被视为 MyEpochType ::

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

警告

请注意 behavior of coerce_compared_value is not inherited by default from that of the base type . 如果 TypeDecorator 正在为某些类型的运算符扩充需要特殊逻辑的类型,此方法 must 被重写。一个关键的例子是当装饰 postgresql.JSONpostgresql.JSONB 类型;默认规则 TypeEngine.coerce_compared_value() 应用于处理索引操作等运算符:

class MyJsonType(TypeDecorator):
    impl = postgresql.JSON

    def coerce_compared_value(self, op, value):
        return self.impl.coerce_compared_value(op, value)

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

class Comparator(expr)

基地: sqlalchemy.types.Comparator

__eq__(other)

继承 __eq__() 方法 ColumnOperators

实施 == 操作符。

在列上下文中,生成子句 a = b . 如果目标是 None 生产 a IS NULL .

__le__(other)

继承 __le__() 方法 ColumnOperators

实施 <= 操作符。

在列上下文中,生成子句 a <= b .

__lt__(other)

继承 __lt__() 方法 ColumnOperators

实施 < 操作符。

在列上下文中,生成子句 a < b .

__ne__(other)

继承 __ne__() 方法 ColumnOperators

实施 != 操作符。

在列上下文中,生成子句 a != b . 如果目标是 None 生产 a IS NOT NULL .

all_()

继承 all_() 方法 ColumnOperators

产生一个 all_() 针对父对象的子句。

此运算符仅适用于标量子查询对象,或某些后端的列表达式适用于数组类型,例如::

# postgresql '5 = ALL (somearray)'
expr = 5 == mytable.c.somearray.all_()

# mysql '5 = ALL (SELECT value FROM table)'
expr = 5 == select([table.c.value]).as_scalar().all_()

参见

all_() -独立版本

any_() -任何操作符

1.1 新版功能.

any_()

继承 any_() 方法 ColumnOperators

产生一个 any_() 针对父对象的子句。

此运算符仅适用于标量子查询对象,或某些后端的列表达式适用于数组类型,例如::

# postgresql '5 = ANY (somearray)'
expr = 5 == mytable.c.somearray.any_()

# mysql '5 = ANY (SELECT value FROM table)'
expr = 5 == select([table.c.value]).as_scalar().any_()

参见

any_() -独立版本

all_() -所有操作符

1.1 新版功能.

asc()

继承 asc() 方法 ColumnOperators

产生一个 asc() 针对父对象的子句。

between(cleft, cright, symmetric=False)

继承 between() 方法 ColumnOperators

产生一个 between() 在给定上下限的情况下,针对父对象的子句。

bool_op(opstring, precedence=0)

继承 bool_op() 方法 Operators

返回自定义布尔运算符。

这个方法是调用 Operators.op() 并通过 Operators.op.is_comparison 标记为真。

1.2.0b3 新版功能.

collate(collation)

继承 collate() 方法 ColumnOperators

产生一个 collate() 在给定排序规则字符串的情况下,对父对象执行子句。

参见

collate()

concat(other)

继承 concat() 方法 ColumnOperators

实现“concat”运算符。

在列上下文中,生成子句 a || b 或使用 concat() mysql上的操作符。

contains(other, **kwargs)

继承 contains() 方法 ColumnOperators

实现“contains”运算符。

生成一个类似表达式,该表达式根据字符串值中间的匹配项进行测试:

column LIKE '%' || <other> || '%'

例如。::

stmt = select([sometable]).\
    where(sometable.c.column.contains("foobar"))

因为操作符使用 LIKE ,通配符 "%""_" 存在于<other>表达式中的也将表现为通配符。对于文本字符串值, ColumnOperators.contains.autoescape 标志可以设置为 True 将转义应用于字符串值中出现的这些字符,以便它们与自身匹配,而不是作为通配符匹配。或者, ColumnOperators.contains.escape 参数将建立一个给定字符作为转义字符,当目标表达式不是文本字符串时可以使用该字符。

参数
  • other -- 要比较的表达式。这通常是一个纯字符串值,但也可以是任意的SQL表达式。类似通配符 %_ 默认情况下不转义,除非 ColumnOperators.contains.autoescape 标志设置为真。

  • autoescape -- 布尔值;如果为true,则在like表达式中建立转义符,然后将其应用于 "%""_" 以及转义符本身在比较值中,该值被假定为文本字符串而不是SQL表达式。表达式如::somecolumn.contains(“foo%bar”,autoescape=true)将呈现为::somecolumn,如“%”。|| :param || '%' ESCAPE '/' With the value of :param as "foo/%bar". .. versionadded:: 1.2 .. versionchanged:: 1.2.0 The ColumnOperators.contains.autoescape 参数现在是一个简单的布尔值而不是一个字符;转义字符本身也被转义,并默认为正斜杠,可以使用 ColumnOperators.contains.escape 参数。

  • escape -- 一个字符,当给定时将用 ESCAPE 关键字将该字符建立为转义字符。然后可以将此字符置于 %_ 允许它们充当自己而不是通配符。表达式如::somecolumn.contains(“foo/%bar”,escape=“^”)将呈现为::somecolumn,如“%”。|| :param || '%' ESCAPE '^' The parameter may also be combined with ColumnOperators.contains.autoescape ::someColumn.contains(“foo%bar^bat”,escape=“^”,autoescape=true),其中,给定的文本参数将转换为 "foo^%bar^^bat" 在被传递到数据库之前。

desc()

继承 desc() 方法 ColumnOperators

产生一个 desc() 针对父对象的子句。

distinct()

继承 distinct() 方法 ColumnOperators

产生一个 distinct() 针对父对象的子句。

endswith(other, **kwargs)

继承 endswith() 方法 ColumnOperators

实现“endswith”运算符。

生成一个类似表达式,该表达式根据字符串值末尾的匹配项进行测试:

column LIKE '%' || <other>

例如。::

stmt = select([sometable]).\
    where(sometable.c.column.endswith("foobar"))

因为操作符使用 LIKE ,通配符 "%""_" 存在于<other>表达式中的也将表现为通配符。对于文本字符串值, ColumnOperators.endswith.autoescape 标志可以设置为 True 将转义应用于字符串值中出现的这些字符,以便它们与自身匹配,而不是作为通配符匹配。或者, ColumnOperators.endswith.escape 参数将建立一个给定字符作为转义字符,当目标表达式不是文本字符串时可以使用该字符。

参数
  • other -- 要比较的表达式。这通常是一个纯字符串值,但也可以是任意的SQL表达式。类似通配符 %_ 默认情况下不转义,除非 ColumnOperators.endswith.autoescape 标志设置为真。

  • autoescape -- 布尔值;如果为true,则在like表达式中建立转义符,然后将其应用于 "%""_" 以及转义符本身在比较值中,该值被假定为文本字符串而不是SQL表达式。表达式如::somecolumn.endswith(“foo%bar”,autoescape=true)将呈现为::somecolumn,如“%”。|| :param ESCAPE '/' With the value of :param as "foo/%bar". .. versionadded:: 1.2 .. versionchanged:: 1.2.0 The ColumnOperators.endswith.autoescape 参数现在是一个简单的布尔值而不是一个字符;转义字符本身也被转义,并默认为正斜杠,可以使用 ColumnOperators.endswith.escape 参数。

  • escape -- 一个字符,当给定时将用 ESCAPE 关键字将该字符建立为转义字符。然后可以将此字符置于 %_ 允许它们充当自己而不是通配符。表达式如::somecolumn.endswith(“foo/%bar”,escape=“^”)将呈现为::somecolumn,如“%”。|| :param ESCAPE '^' The parameter may also be combined with ColumnOperators.endswith.autoescape ::someColumn.endsWith(“foo%bar^bat”,escape=“^”,autoescape=true),其中,给定的文本参数将转换为 "foo^%bar^^bat" 在被传递到数据库之前。

ilike(other, escape=None)

继承 ilike() 方法 ColumnOperators

实施 ilike 运算符,例如不区分大小写的like。

在列上下文中,生成以下任一形式的表达式:

lower(a) LIKE lower(other)

或者在支持ilike运算符的后端:

a ILIKE other

例如。::

stmt = select([sometable]).\
    where(sometable.c.column.ilike("%foobar%"))
参数
  • other -- 要比较的表达式

  • escape -- 可选转义符,呈现 ESCAPE 关键字,例如:somecolumn.ilike(“foo/%bar”,escape=“/”)

in_(other)

继承 in_() 方法 ColumnOperators

实施 in 操作符。

在列上下文中,生成子句 column IN <other> .

给定参数 other 可能是:

  • 文字值列表,例如:

    stmt.where(column.in_([1, 2, 3]))

    在此调用表单中,项目列表将转换为一组与给定列表长度相同的绑定参数:

    WHERE COL IN (?, ?, ?)
  • 空列表,例如:

    stmt.where(column.in_([]))

    在此调用形式中,表达式呈现“false”表达式,例如:

    WHERE 1 != 1

    这个“假”表达式在旧的sqlAlchemy版本中历史上有不同的行为,请参见 create_engine.empty_in_strategy 对于行为选项。

    在 1.2 版更改: 简化了“空入”表达式的行为

  • 绑定参数,例如 bindparam() ,如果包含 bindparam.expanding 标志:

    stmt.where(column.in_(bindparam('value', expanding=True)))

    在此调用表单中,表达式呈现一个特殊的非SQL占位符表达式,其外观如下:

    WHERE COL IN ([EXPANDING_value])

    此占位符表达式在语句执行时被截取,以便转换为前面所示的绑定参数表单的变量号。如果语句的执行方式为:

    connection.execute(stmt, {"value": [1, 2, 3]})

    将为数据库传递每个值的绑定参数:

    WHERE COL IN (?, ?, ?)

    1.2 新版功能: 添加了“扩展”绑定参数

    如果传递空列表,将呈现一个特定于正在使用的数据库的特殊“空列表”表达式。在sqlite上:

    WHERE COL IN (SELECT 1 FROM (SELECT 1) WHERE 1!=1)

    1.3 新版功能: “expanding”绑定参数现在支持空列表

  • select() 构造,通常是相关的标量选择:

    stmt.where(
        column.in_(
            select([othertable.c.y]).
            where(table.c.x == othertable.c.x)
        )
    )

    在这个调用表单中, ColumnOperators.in_() 按给定呈现:

    WHERE COL IN (SELECT othertable.y
    FROM othertable WHERE othertable.x = table.x)
参数

other -- 文字列表,a select() 构造,或 bindparam() 构造,包括 bindparam.expanding 标志设置为真。

is_(other)

继承 is_() 方法 ColumnOperators

实施 IS 操作符。

通常情况下, IS 与以下值比较时自动生成 None ,决定 NULL . 但是,明确使用 IS 如果与某些平台上的布尔值进行比较,可能是可取的。

is_distinct_from(other)

实施 IS DISTINCT FROM 操作符。

在大多数平台上呈现“a与b不同”;在某些平台上,例如sqlite可能呈现“a不是b”。

1.1 新版功能.

isnot(other)

继承 isnot() 方法 ColumnOperators

实施 IS NOT 操作符。

通常情况下, IS NOT 与以下值比较时自动生成 None ,决定 NULL . 但是,明确使用 IS NOT 如果与某些平台上的布尔值进行比较,可能是可取的。

isnot_distinct_from(other)

实施 IS NOT DISTINCT FROM 操作符。

在大多数平台上呈现“a与b不同”;在某些平台上,例如sqlite可能呈现“a是b”。

1.1 新版功能.

like(other, escape=None)

继承 like() 方法 ColumnOperators

实施 like 操作符。

在列上下文中,生成表达式::

a LIKE other

例如。::

stmt = select([sometable]).\
    where(sometable.c.column.like("%foobar%"))
参数
  • other -- 要比较的表达式

  • escape -- 可选转义符,呈现 ESCAPE 关键字,例如:somecolumn.like(“foo/%bar”,escape=“/”)

match(other, **kwargs)

继承 match() 方法 ColumnOperators

实现特定于数据库的“match”运算符。

match() 尝试解析为后端提供的类似匹配的函数或运算符。示例包括:

  • PostgreSQL-呈现 x @@ to_tsquery(y)

  • MySQL -渲染器 MATCH (x) AGAINST (y IN BOOLEAN MODE)

  • Oracle-呈现 CONTAINS(x, y)

  • 其他后端可能提供特殊的实现。

  • 没有任何特殊实现的后端将发出“match”操作符。例如,这与sqlite兼容。

notilike(other, escape=None)

继承 notilike() 方法 ColumnOperators

实施 NOT ILIKE 操作符。

这相当于使用否定 ColumnOperators.ilike() ,即 ~x.ilike(y) .

notin_(other)

继承 notin_() 方法 ColumnOperators

实施 NOT IN 操作符。

这相当于使用否定 ColumnOperators.in_() ,即 ~x.in_(y) .

在这种情况下 other 是一个空序列,编译器生成一个“empty not in”表达式。这将默认表达式“1=1”在所有情况下都生成“真”。这个 create_engine.empty_in_strategy 可用于更改此行为。

在 1.2 版更改: 这个 ColumnOperators.in_()ColumnOperators.notin_() 现在,默认情况下,运算符为空序列生成一个“静态”表达式。

notlike(other, escape=None)

继承 notlike() 方法 ColumnOperators

实施 NOT LIKE 操作符。

这相当于使用否定 ColumnOperators.like() ,即 ~x.like(y) .

nullsfirst()

产生一个 nullsfirst() 针对父对象的子句。

nullslast()

产生一个 nullslast() 针对父对象的子句。

op(opstring, precedence=0, is_comparison=False, return_type=None)

继承 op() 方法 Operators

生成通用运算符函数。

例如。::

somecolumn.op("*")(5)

生产::

somecolumn * 5

此函数还可用于显式地生成位运算符。例如::

somecolumn.op('&')(0xff)

是中的值的位与 somecolumn .

参数
  • operator -- 将作为该元素和传递给生成函数的表达式之间的中缀运算符输出的字符串。

  • precedence -- 在对表达式加括号时应用于运算符的优先级。当对具有更高优先级的另一个运算符应用时,较低的数字将导致表达式加括号。默认值为 0 低于除逗号之外的所有运算符 (,AS 运算符。值100将大于或等于所有运算符,-100将小于或等于所有运算符。

  • is_comparison -- 如果为真,则该运算符将被视为“比较”运算符,即计算为布尔真/假值,如 ==> 等等。应设置此标志,以便ORM关系可以确定在自定义联接条件中使用的运算符是比较运算符。…versionAdded::0.9.2-添加了 Operators.op.is_comparison 标志。

  • return_type -- 一 TypeEngine 类或对象,它将强制此运算符生成的表达式的返回类型为该类型。默认情况下,指定 Operators.op.is_comparison 将决心 Boolean ,而那些不属于左侧操作数的类型。…versionAdded::1.2.0b3-添加了 Operators.op.return_type 争论。

operate(op, *other, **kwargs)

对参数进行运算。

这是最低级别的操作,提升 NotImplementedError 默认情况下。

在子类上覆盖此项可以允许将公共行为应用于所有操作。例如,重写 ColumnOperators 申请 func.lower() 左右两侧:

class MyComparator(ColumnOperators):
    def operate(self, op, other):
        return op(func.lower(self), func.lower(other))
参数
  • op -- 操作符可调用。

  • *other -- 操作的“另一方”。对于大多数操作,将是单个标量。

  • **kwargs -- 修饰语。这些可由特殊操作符通过,如 ColumnOperators.contains() .

reverse_operate(op, other, **kwargs)

对参数进行反向运算。

用法与 operate() .

startswith(other, **kwargs)

实施 startswith 操作符。

生成一个类似表达式,该表达式根据字符串值开头的匹配项进行测试:

column LIKE <other> || '%'

例如。::

stmt = select([sometable]).\
    where(sometable.c.column.startswith("foobar"))

因为操作符使用 LIKE ,通配符 "%""_" 存在于<other>表达式中的也将表现为通配符。对于文本字符串值, ColumnOperators.startswith.autoescape 标志可以设置为 True 将转义应用于字符串值中出现的这些字符,以便它们与自身匹配,而不是作为通配符匹配。或者, ColumnOperators.startswith.escape 参数将建立一个给定字符作为转义字符,当目标表达式不是文本字符串时可以使用该字符。

参数
  • other -- 要比较的表达式。这通常是一个纯字符串值,但也可以是任意的SQL表达式。类似通配符 %_ 默认情况下不转义,除非 ColumnOperators.startswith.autoescape 标志设置为真。

  • autoescape -- 布尔值;如果为true,则在like表达式中建立转义符,然后将其应用于 "%""_" 以及转义符本身在比较值中,该值被假定为文本字符串而不是SQL表达式。表达式如::somecolumn.startswith(“foo%bar”,autoescape=true)将呈现为::somecolumn-like :param || '%' ESCAPE '/' With the value of :param as "foo/%bar". .. versionadded:: 1.2 .. versionchanged:: 1.2.0 The ColumnOperators.startswith.autoescape 参数现在是一个简单的布尔值而不是一个字符;转义字符本身也被转义,并默认为正斜杠,可以使用 ColumnOperators.startswith.escape 参数。

  • escape -- 一个字符,当给定时将用 ESCAPE 关键字将该字符建立为转义字符。然后可以将此字符置于 %_ 允许它们充当自己而不是通配符。表达式如::somecolumn.startswith(“foo/%bar”,escape=“^”)将呈现为::somecolumn-like :param || '%' ESCAPE '^' The parameter may also be combined with ColumnOperators.startswith.autoescape ::somecolumn.startswith(“foo%bar^bat”,escape=“^”,autoescape=true),其中,给定的文本参数将转换为 "foo^%bar^^bat" 在被传递到数据库之前。

__eq__

继承 __eq__ 属性 object

返回self==值。

__init__(*args, **kwargs)

构建一个 TypeDecorator .

此处发送的参数将传递给分配给 impl 类级属性,假定 impl 是可调用的,并且结果对象被分配给 self.impl 实例属性(从而覆盖相同名称的类属性)。

如果等级 impl 不是可调用的(异常情况),它将被分配给与“原样”相同的实例属性,忽略传递给构造函数的参数。

子类可以重写此项以自定义 self.impl 完全。

__le__

继承 __le__ 属性 object

返回self<=value。

__lt__

继承 __lt__ 属性 object

返回self<value。

__ne__

继承 __ne__ 属性 object

回归自我!=值。

adapt(cls, **kw)

继承 adapt() 方法 TypeEngine

给出一个“impl”类来处理这种类型的“改编”形式。

此方法在内部用于将泛型类型与特定方言的“实现”类型相关联。

bind_expression(bindparam)

“给定绑定值(即 BindParameter 实例),返回一个SQL表达式。

这通常是一个在语句中包装现有绑定参数的SQL函数。它用于特殊数据类型,这些数据类型需要将文本包装在某些特殊的数据库函数中,以便将应用程序级值强制为特定于数据库的格式。它类似于SQL TypeEngine.bind_processor() 方法。

该方法在语句编译时进行评估,而不是在语句构造时进行评估。

请注意,此方法在实现时,应始终返回完全相同的结构,而不返回任何条件逻辑,因为它可以在针对任意数量的绑定参数集的executeMany()调用中使用。

bind_processor(dialect)

为给定的提供绑定值处理函数 Dialect .

这是实现 TypeEngine 约束值转换合同。 TypeDecorator 将包装用户定义的 process_bind_param() 在这里。

用户定义的代码可以直接重写这个方法,尽管它可能最适合使用 process_bind_param() 以便处理所提供的 self.impl 保持。

参数

dialect -- 方言实例正在使用中。

此方法与 result_processor() 此类的方法。

coerce_compared_value(op, value)

为表达式中的“强制”python值建议类型。

默认情况下,返回self。当使用此类型的对象位于表达式的左侧或右侧,而普通的python对象尚未指定SQLAlchemy类型时,表达式系统将调用此方法::

expr = table.c.somecolumn + 35

如果以上,如果 somecolumn 使用此类型,将使用值调用此方法 operator.add35 . 返回值是应用于 35 对于这个特殊的操作。

coerce_to_is_types = (<class 'NoneType'>,)

指定在表达式级别应强制为“is<constant>”的python类型,当使用 == (同样) IS NOT!= .

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

TypeDecorator 将此列表修改为仅包含 NoneType ,因为处理布尔类型的typedecorator实现是常见的。

习俗 TypeDecorator 类可以重写此属性以返回空元组,在这种情况下,不会将任何值强制为常量。

column_expression(column)

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

这通常是一个SQL函数,它在select语句的columns子句中呈现列表达式。它用于特殊数据类型,这些数据类型要求将列包装在某些特殊的数据库函数中,以便在发送回应用程序之前强制该值。它类似于SQL TypeEngine.result_processor() 方法。

该方法在语句编译时进行评估,而不是在语句构造时进行评估。

comparator_factory

在类型级别定义的自定义比较操作的基类。见 TypeEngine.comparator_factory .

compare_against_backend(dialect, conn_type)

将此类型与给定的后端类型进行比较。

此函数当前没有为SQLAlchemy类型实现,并且对于所有内置类型,将返回 None . 但是,它可以由用户定义的类型实现,在该类型中,模式比较工具(如alembic autogenerate)可以使用它。

SQLAlchemy的未来版本也可能为内置类型实现此方法。

如果此类型与给定类型等效,则函数应返回true;该类型通常从数据库反映出来,因此应是特定于数据库的。使用中的方言也会被传递。它还可以返回false来断言类型不是等效的。

参数
  • dialect -- 一 Dialect 这与比较有关。

  • conn_type -- 从后端反射的类型对象。

1.0.3 新版功能.

compare_values(x, y)

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

默认情况下,此调用 TypeEngine.compare_values() 在底层“impl”中,通常使用python equals运算符 == .

ORM使用此函数将原始加载值与截取的“已更改”值进行比较,以确定是否发生了净更改。

compile(dialect=None)

继承 compile() 方法 TypeEngine

生成此的字符串编译形式 TypeEngine .

在没有参数的情况下调用时,使用“默认”方言生成字符串结果。

参数

dialect -- 一 Dialect 实例。

copy(**kw)

生成此的副本 TypeDecorator 实例。

这是一个肤浅的副本,用于完成 TypeEngine 合同。它通常不需要重写,除非用户定义 TypeDecorator 具有应进行深度复制的本地状态。

dialect_impl(dialect)

继承 dialect_impl() 方法 TypeEngine

为此返回特定于方言的实现 TypeEngine .

evaluates_none()

返回具有 should_evaluate_none 标志设置为真。

例如。::

Table(
    'some_table', metadata,
    Column(
        String(50).evaluates_none(),
        nullable=True,
        server_default='no value')
)

ORM使用此标志指示 None 传递给insert语句中的列,而不是从insert语句中省略该列,这将触发列级默认值。它还允许具有与python none值相关联的特殊行为的类型指示该值不必转换为sql空值;这方面的主要示例是希望持久化json值的json类型。 'null' .

在所有情况下,可以使用 null 在INSERT语句中或与ORM映射属性关联的SQL构造。

注解

“evaluations none”标志 not 应用于值 None 传递给 Column.defaultColumn.server_default ;在这些情况下, None 仍然意味着“不违约”。

1.1 新版功能.

参见

对具有默认值的列强制空值 -在ORM文档中

postgresql.JSON.none_as_null -PostgreSQL JSON与此标志的交互。

TypeEngine.should_evaluate_none -类级别标志

get_dbapi_type(dbapi)

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

默认情况下,此调用 TypeEngine.get_dbapi_type() 基本的“impl”。

literal_processor(dialect)

为给定的提供文本处理函数 Dialect .

这里的子类通常会覆盖 TypeDecorator.process_literal_param() 而不是直接用这种方法。

默认情况下,此方法使用 TypeDecorator.process_bind_param() 如果实现了该方法,那么 TypeDecorator.process_literal_param() 不是。这里的基本原理是 TypeDecorator 通常处理数据库表示层之上的数据的python转换。值转换为 TypeDecorator.process_bind_param() 然后,基础类型将处理它是否需要作为绑定参数呈现给DBAPI,还是作为内联SQL值呈现给数据库。

0.9.0 新版功能.

load_dialect_impl(dialect)

返回A TypeEngine 与方言相对应的对象。

这是一个终端用户覆盖钩子,可以根据给定的方言提供不同的类型。它被 TypeDecorator 执行 type_engine() 以帮助确定最终应为给定的 TypeDecorator .

默认情况下返回 self.impl .

process_bind_param(value, dialect)

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

子类重写此方法以返回应传递给基础的值 TypeEngine 对象,从那里到DBAPI execute() 方法。

该操作可以是执行自定义行为所需的任何操作,例如转换或序列化数据。这也可以用作验证逻辑的钩子。

此操作的设计应考虑到反向操作,这将是此类的过程结果值方法。

参数
  • value -- 要操作的数据,属于子类中此方法所期望的任何类型。可以是 None .

  • dialect -- 这个 Dialect 在使用中。

process_literal_param(value, dialect)

接收要在语句内内联呈现的文本参数值。

当编译器在不使用绑定的情况下呈现文本值时,通常在DDL中使用此方法,例如在列的“服务器默认值”或检查约束中的表达式中。

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

0.9.0 新版功能.

process_result_value(value, dialect)

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

子类应该实现这个方法来操作从数据库中获取的数据。

子类重写此方法以返回应传递回应用程序的值,给定的值已由基础处理 TypeEngine 对象,最初来自dbapi cursor方法 fetchone() 或者类似的。

该操作可以是执行自定义行为所需的任何操作,例如转换或序列化数据。这也可以用作验证逻辑的钩子。

参数
  • value -- 要操作的数据,属于子类中此方法所期望的任何类型。可以是 None .

  • dialect -- 这个 Dialect 在使用中。

此操作应设计为通过此类的“process-bind-param”方法可逆。

python_type

继承 python_type 属性 TypeEngine

如果已知,则返回此类型的实例预期返回的python类型对象。

基本上,对于那些强制执行返回类型的类型,或者对于所有公共DBAPI(如 int 例如),将返回该类型。

如果未定义返回类型,则引发 NotImplementedError .

请注意,任何类型在SQL中也可以容纳空值,这意味着您还可以返回 None 从实践中的任何类型。

result_processor(dialect, coltype)

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

这是实现 TypeEngine 结果值转换合同。 TypeDecorator 将包装用户定义的 process_result_value() 在这里。

用户定义的代码可以直接重写这个方法,尽管它可能最适合使用 process_result_value() 以便处理所提供的 self.impl 保持。

参数
  • dialect -- 方言实例正在使用中。

  • coltype -- SQLAlchemy数据类型

此方法与 bind_processor() 此类的方法。

type_engine(dialect)

返回特定方言 TypeEngine 这个的实例 TypeDecorator .

在大多数情况下,这会返回 TypeEngine 类型由表示 self.impl . 利用 dialect_impl() 但也要穿越包裹 TypeDecorator 实例。可以通过重写在此处自定义行为 load_dialect_impl() .

with_variant(type_, dialect_name)

继承 with_variant() 方法 TypeEngine

生成一个新的类型对象,该对象将在应用于给定名称的方言时使用给定的类型。

例如。::

from sqlalchemy.types import String
from sqlalchemy.dialects import mysql

s = String()

s = s.with_variant(mysql.VARCHAR(collation='foo'), 'mysql')

建筑 TypeEngine.with_variant() 总是从“回退”类型到特定于方言的类型。返回的类型是的实例 Variant 它本身提供了 Variant.with_variant() 可以重复调用。

参数
  • type_ -- 一 TypeEngine 当使用给定名称的方言时,将从原始类型中选择作为变体。

  • dialect_name -- 使用此类型的方言的基名称。(即 'postgresql''mysql' 等)

typedecorator方法

几把钥匙 TypeDecorator 方法如下。

将编码字符串强制为Unicode

关于 Unicode 类型是它要处理的 only 用Python unicode 对象在python端,这意味着作为绑定参数传递给它的值的形式必须是 u'some string' 如果使用的是python 2而不是3。它执行的编码/解码功能仅适用于使用中的DBAPI所需的功能,并且主要是私有实现细节。

可以安全地接收python字节串的类型的用例,即包含非ascii字符的字符串,而不是 u'' 在python 2中,可以使用 TypeDecorator 根据需要强制:

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连接器,如果传递的小数位数太多,则会阻塞。这里有一个菜谱可以把它们四舍五入:

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

后端不可知guid类型

接收并返回python uuid()对象。在其他后端使用postgresql、char(32)时使用pg uuid类型,以字符串化十六进制格式存储它们。如果需要,可以修改为在char(16)中存储二进制:

from sqlalchemy.types import TypeDecorator, CHAR
from sqlalchemy.dialects.postgresql import UUID
import uuid

class GUID(TypeDecorator):
    """Platform-independent GUID type.

    Uses PostgreSQL's UUID type, otherwise uses
    CHAR(32), storing as stringified hex values.

    """
    impl = CHAR

    def load_dialect_impl(self, dialect):
        if dialect.name == 'postgresql':
            return dialect.type_descriptor(UUID())
        else:
            return dialect.type_descriptor(CHAR(32))

    def process_bind_param(self, value, dialect):
        if value is None:
            return value
        elif dialect.name == 'postgresql':
            return str(value)
        else:
            if not isinstance(value, uuid.UUID):
                return "%.32x" % uuid.UUID(value).int
            else:
                # hexstring
                return "%.32x" % value.int

    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

封送JSON字符串

这种类型的用途 simplejson 将python数据结构封送到JSON或从JSON传出。可以修改为使用Python的内置JSON编码器:

from sqlalchemy.types import TypeDecorator, VARCHAR
import json

class JSONEncodedDict(TypeDecorator):
    """Represents an immutable structure as a json-encoded string.

    Usage::

        JSONEncodedDict(255)

    """

    impl = VARCHAR

    def process_bind_param(self, value, dialect):
        if value is not None:
            value = json.dumps(value)

        return value

    def process_result_value(self, value, dialect):
        if value is not None:
            value = json.loads(value)
        return value

添加可变性

默认情况下,ORM不会检测到上述类型的“可变性”,也就是说,对值的就地更改将不会被检测到,也不会被刷新。如果不采取进一步步骤,则需要在每个父对象上用新值替换现有值,以检测更改:

obj.json_value["key"] = "value"  # will *not* be detected by the ORM

obj.json_value = {"key": "value"}  # *will* be detected by the ORM

上述限制可能很好,因为许多应用程序可能不要求值在创建后发生变化。对于那些有这个需求的人,最好使用 sqlalchemy.ext.mutable 延伸。对于面向字典的JSON结构,我们可以将其应用为:

json_type = MutableDict.as_mutable(JSONEncodedDict)

class MyClass(Base):
    #  ...

    json_data = Column(json_type)

参见

突变跟踪

处理比较运算

的默认行为 TypeDecorator 是将任何表达式的“右手边”强制为同一类型。对于类似JSON的类型,这意味着所使用的任何运算符都必须对JSON有意义。在某些情况下,用户可能希望该类型在某些情况下的行为类似于JSON,而在其他情况下则是纯文本。一个例子是,如果想要为JSON类型处理like操作符。对于JSON结构,like没有意义,但是对于底层的文本表示它确实有意义。为了达到这个目的 JSONEncodedDict 我们需要 胁迫 使用将列转换为文本形式 cast()type_coerce() 在尝试使用此运算符之前:

from sqlalchemy import type_coerce, String

stmt = select([my_table]).where(
    type_coerce(my_table.c.json_data, String).like('%foo%'))

TypeDecorator 提供一个内置的系统,用于基于运算符处理类似的类型转换。如果我们希望经常在JSON对象被解释为字符串时使用LIKE运算符,我们可以通过重写 TypeDecorator.coerce_compared_value() 方法:

from sqlalchemy.sql import operators
from sqlalchemy import String

class JSONEncodedDict(TypeDecorator):

    impl = VARCHAR

    def coerce_compared_value(self, op, value):
        if op in (operators.like_op, operators.notlike_op):
            return String()
        else:
            return self

    def process_bind_param(self, value, dialect):
        if value is not None:
            value = json.dumps(value)

        return value

    def process_result_value(self, value, dialect):
        if value is not None:
            value = json.loads(value)
        return value

上面只是处理类似“like”的操作符的一种方法。其他申请可能希望提高 NotImplementedError 对于对JSON对象(如“like”)没有意义的运算符,而不是自动强制转换为文本。

应用SQL级绑定/结果处理

如本节所示 扩充现有类型 ,sqlAlchemy允许在参数发送到语句时以及从数据库加载结果行时调用python函数,以便在值发送到数据库或从数据库加载时对其应用转换。也可以定义SQL级别的转换。这里的基本原理是,只有关系数据库包含强制应用程序和持久性格式之间的传入和传出数据所必需的一系列特定函数。示例包括使用数据库定义的加密/解密函数,以及处理地理数据的存储过程。PostGIS对PostgreSQL的扩展包括大量的SQL函数,这些函数是将数据强制转换为特定格式所必需的。

任何 TypeEngineUserDefinedTypeTypeDecorator 子类可以包括 TypeEngine.bind_expression() 和/或 TypeEngine.column_expression() ,当定义为返回非“none”值时,它应返回 ColumnElement 要注入到SQL语句中的表达式,可以是环绕绑定参数,也可以是列表达式。例如,构建 Geometry 将应用PostGIS功能的类型 ST_GeomFromText 所有输出值和函数 ST_AsText 对于所有传入的数据,我们可以创建自己的子类 UserDefinedType 这些方法与 func ::

from sqlalchemy import func
from sqlalchemy.types import UserDefinedType

class Geometry(UserDefinedType):
    def get_col_spec(self):
        return "GEOMETRY"

    def bind_expression(self, bindvalue):
        return func.ST_GeomFromText(bindvalue, type_=self)

    def column_expression(self, col):
        return func.ST_AsText(col, type_=self)

我们可以申请 Geometry 键入 Table 元数据并将其用于 select() 结构:

geometry = Table('geometry', metadata,
              Column('geom_id', Integer, primary_key=True),
              Column('geom_data', Geometry)
            )

print(select([geometry]).where(
  geometry.c.geom_data == 'LINESTRING(189412 252431,189631 259122)'))

生成的SQL根据需要嵌入这两个函数。 ST_AsText 应用于columns子句,以便在传递到结果集之前通过函数运行返回值,以及 ST_GeomFromText 对绑定参数运行,以便转换传入的值::

SELECT geometry.geom_id, ST_AsText(geometry.geom_data) AS geom_data_1
FROM geometry
WHERE geometry.geom_data = ST_GeomFromText(:geom_data_2)

这个 TypeEngine.column_expression() 方法与编译器的机制交互,以便SQL表达式不会干扰包装表达式的标记。例如,如果我们 select() 反对 label() 在表达式中,字符串标签被移动到包装表达式的外部:

print(select([geometry.c.geom_data.label('my_data')]))

输出:

SELECT ST_AsText(geometry.geom_data) AS my_data
FROM geometry

另一个例子是我们装饰 postgresql.BYTEA 提供一个 PGPString ,这将利用PostgreSQL pgcrypto 透明加密/解密值的扩展名:

from sqlalchemy import create_engine, String, select, func, \
        MetaData, Table, Column, type_coerce, TypeDecorator

from sqlalchemy.dialects.postgresql import BYTEA

class PGPString(TypeDecorator):
    impl = BYTEA

    def __init__(self, passphrase):
        super(PGPString, self).__init__()
        self.passphrase = passphrase

    def bind_expression(self, bindvalue):
        # convert the bind's type from PGPString to
        # String, so that it's passed to psycopg2 as is without
        # a dbapi.Binary wrapper
        bindvalue = type_coerce(bindvalue, String)
        return func.pgp_sym_encrypt(bindvalue, self.passphrase)

    def column_expression(self, col):
        return func.pgp_sym_decrypt(col, self.passphrase)

metadata = MetaData()
message = Table('message', metadata,
                Column('username', String(50)),
                Column('message',
                    PGPString("this is my passphrase")),
            )

engine = create_engine("postgresql://scott:tiger@localhost/test", echo=True)
with engine.begin() as conn:
    metadata.create_all(conn)

    conn.execute(message.insert(), username="some user",
                                message="this is my message")

    print(conn.scalar(
            select([message.c.message]).\
                where(message.c.username == "some user")
        ))

这个 pgp_sym_encryptpgp_sym_decrypt 函数应用于insert和select语句:

INSERT INTO message (username, message)
  VALUES (%(username)s, pgp_sym_encrypt(%(message)s, %(pgp_sym_encrypt_1)s))
  {'username': 'some user', 'message': 'this is my message',
    'pgp_sym_encrypt_1': 'this is my passphrase'}

SELECT pgp_sym_decrypt(message.message, %(pgp_sym_decrypt_1)s) AS message_1
  FROM message
  WHERE message.username = %(username_1)s
  {'pgp_sym_decrypt_1': 'this is my passphrase', 'username_1': 'some user'}

参见

PostGIS集成

重新定义和创建新的运算符

SQLAlchemy核心定义了一组固定的表达式运算符,可用于所有列表达式。其中一些操作具有重载Python内置运算符的效果;此类运算符的示例包括 ColumnOperators.__eq__() (table.c.somecolumn == 'foo'ColumnOperators.__invert__() (~table.c.flagColumnOperators.__add__() (table.c.x + table.c.y )其他运算符作为列表达式上的显式方法公开,例如 ColumnOperators.in_() (table.c.value.in_(['x', 'y'])ColumnOperators.like() (table.c.value.like('%ed%')

核心表达式在所有情况下都构造查询表达式的类型,以确定现有运算符的行为,并查找不属于内置集的其他运算符。这个 TypeEngine 基类定义根“比较”实现 TypeEngine.Comparator 和许多特定类型提供了自己的此类子实现。用户定义的 TypeEngine.Comparator 实现可以直接构建到特定类型的简单子类中,以便重写或定义新的操作。下面,我们创建一个 Integer 重写的子类 ColumnOperators.__add__() 操作符:

from sqlalchemy import Integer

class MyInt(Integer):
    class comparator_factory(Integer.Comparator):
        def __add__(self, other):
            return self.op("goofy")(other)

上面的配置创建了一个新类 MyInt ,从而确定 TypeEngine.comparator_factory 属性引用一个新类,将 TypeEngine.Comparator 与关联的类 Integer 类型。

用法:

>>> sometable = Table("sometable", metadata, Column("data", MyInt))
>>> print(sometable.c.data + 5)
sometable.data goofy :data_1

实施 ColumnOperators.__add__() 由所属的SQL表达式通过实例化 TypeEngine.Comparator 把自己当作 expr 属性。表达式系统的机制是这样的:操作以递归方式继续,直到表达式对象生成新的SQL表达式构造。上面,我们也可以这么说 self.expr.op("goofy")(other) 而不是 self.op("goofy")(other) .

使用时 Operators.op() 对于返回布尔结果的比较操作, Operators.op.is_comparison 标志应设置为 True ::

class MyInt(Integer):
    class comparator_factory(Integer.Comparator):
        def is_frobnozzled(self, other):
            return self.op("--is_frobnozzled->", is_comparison=True)(other)

添加到 TypeEngine.Comparator 在拥有的SQL表达式上使用 __getattr__ 方案,它公开添加到 TypeEngine.Comparator 拥有 ColumnElement . 例如,要添加 log() 整型函数:

from sqlalchemy import Integer, func

class MyInt(Integer):
    class comparator_factory(Integer.Comparator):
        def log(self, other):
            return func.log(self.expr, other)

使用上述类型:

>>> print(sometable.c.data.log(5))
log(:log_1, :log_2)

一元运算也是可能的。例如,为了添加PostgreSQL阶乘运算符的实现,我们将 UnaryExpressioncustom_op 要生成阶乘表达式:

from sqlalchemy import Integer
from sqlalchemy.sql.expression import UnaryExpression
from sqlalchemy.sql import operators

class MyInteger(Integer):
    class comparator_factory(Integer.Comparator):
        def factorial(self):
            return UnaryExpression(self.expr,
                        modifier=operators.custom_op("!"),
                        type_=MyInteger)

使用上述类型:

>>> from sqlalchemy.sql import column
>>> print(column('x', MyInteger).factorial())
x !

创建新类型

这个 UserDefinedType 类作为一个简单的基类提供,用于定义全新的数据库类型。使用此项表示SQLAlchemy不知道的本机数据库类型。如果只需要python转换行为,请使用 TypeDecorator 相反。

class sqlalchemy.types.UserDefinedType

基地: sqlalchemy.types.TypeEngine

用户定义类型的基。

这应该是新类型的基础。注意,在大多数情况下, TypeDecorator 可能更合适:

import sqlalchemy.types as types

class MyType(types.UserDefinedType):
    def __init__(self, precision = 8):
        self.precision = precision

    def get_col_spec(self, **kw):
        return "MYTYPE(%s)" % self.precision

    def bind_processor(self, dialect):
        def process(value):
            return value
        return process

    def result_processor(self, dialect, coltype):
        def process(value):
            return value
        return process

一旦生成类型,它立即可用:

table = Table('foo', meta,
    Column('id', Integer, primary_key=True),
    Column('data', MyType(16))
    )

这个 get_col_spec() 在大多数情况下,方法将接收关键字参数 type_expression 它引用正在编译的类型的所属表达式,例如 Columncast() 构建。仅当方法接受关键字参数(例如 **kw )在它的参数签名中,内省用于检查这一点,以便支持此函数的遗留形式。

1.0.0 新版功能: 所属表达式传递给 get_col_spec() 方法通过关键字参数 type_expression ,如果它收到 **kw 在它的签名上。

class Comparator(expr)

基地: sqlalchemy.types.Comparator

coerce_compared_value(op, value)

为表达式中的“强制”python值建议类型。

的默认行为 UserDefinedType 与…相同 TypeDecorator ;默认返回 self ,假定比较值应强制为与此值相同的类型。见 TypeDecorator.coerce_compared_value() 更多细节。

comparator_factory

UserDefinedType.Comparator 的别名