Release: 1.4.25 | Release Date: September 22, 2021

SQLAlchemy 1.4 Documentation

混合属性

在ORM映射类上定义具有“混合”行为的属性。

“混合”是指属性在类级别和实例级别定义了不同的行为。

这个 hybrid 扩展提供了一种特殊形式的方法修饰器,大约有50行代码,几乎不依赖于其他的sqlacalchemy。理论上,它可以与任何基于描述符的表达式系统一起工作。

考虑映射 Interval ,表示整数 startend 价值观。我们可以在生成类级SQL表达式的映射类上定义更高级别的函数,在实例级定义python表达式计算。下面,每个功能都用 hybrid_methodhybrid_property 可能收到 self 作为类的实例,或作为类本身:

from sqlalchemy import Column, Integer
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import Session, aliased
from sqlalchemy.ext.hybrid import hybrid_property, hybrid_method

Base = declarative_base()

class Interval(Base):
    __tablename__ = 'interval'

    id = Column(Integer, primary_key=True)
    start = Column(Integer, nullable=False)
    end = Column(Integer, nullable=False)

    def __init__(self, start, end):
        self.start = start
        self.end = end

    @hybrid_property
    def length(self):
        return self.end - self.start

    @hybrid_method
    def contains(self, point):
        return (self.start <= point) & (point <= self.end)

    @hybrid_method
    def intersects(self, other):
        return self.contains(other.start) | self.contains(other.end)

上面, length 属性返回 endstart 属性。以…为例 Interval ,此减法在python中进行,使用普通的python描述符机制:

>>> i1 = Interval(5, 10)
>>> i1.length
5

在处理 Interval 类本身,则 hybrid_property 描述符在给定的情况下计算函数体 Interval 类作为参数初始化,该参数在使用SQLAlChemy表达式机制求值时(这里使用 QueryableAttribute.expression 访问器)返回新的SQL表达式::

>>> print(Interval.length.expression)
interval."end" - interval.start

>>> print(Session().query(Interval).filter(Interval.length > 10))
SELECT interval.id AS interval_id, interval.start AS interval_start,
interval."end" AS interval_end
FROM interval
WHERE interval."end" - interval.start > :param_1

ORM方法,例如 Query.filter_by() 普遍使用 getattr() 要定位属性,也可以与混合属性一起使用:

>>> print(Session().query(Interval).filter_by(length=5))
SELECT interval.id AS interval_id, interval.start AS interval_start,
interval."end" AS interval_end
FROM interval
WHERE interval."end" - interval.start = :param_1

这个 Interval 类示例还演示了两种方法, contains()intersects() ,装饰有 hybrid_method . 这个修饰器将相同的思想应用于 hybrid_property 适用于属性。方法返回布尔值,并利用python |& 按位运算符生成等效的实例级和SQL表达式级布尔行为:

>>> i1.contains(6)
True
>>> i1.contains(15)
False
>>> i1.intersects(Interval(7, 18))
True
>>> i1.intersects(Interval(25, 29))
False

>>> print(Session().query(Interval).filter(Interval.contains(15)))
SELECT interval.id AS interval_id, interval.start AS interval_start,
interval."end" AS interval_end
FROM interval
WHERE interval.start <= :start_1 AND interval."end" > :end_1

>>> ia = aliased(Interval)
>>> print(Session().query(Interval, ia).filter(Interval.intersects(ia)))
SELECT interval.id AS interval_id, interval.start AS interval_start,
interval."end" AS interval_end, interval_1.id AS interval_1_id,
interval_1.start AS interval_1_start, interval_1."end" AS interval_1_end
FROM interval, interval AS interval_1
WHERE interval.start <= interval_1.start
    AND interval."end" > interval_1.start
    OR interval.start <= interval_1."end"
    AND interval."end" > interval_1."end"

定义不同于属性行为的表达式行为

我们使用的 &| 上面的按位运算符很幸运,因为我们的函数对两个布尔值进行了运算,以返回一个新的布尔值。在许多情况下,in-python函数和sqlAlchemy SQL表达式的构造有足够的差异,因此应该定义两个单独的python表达式。这个 hybrid 装饰师定义 hybrid_property.expression() 用于此目的的修饰符。例如,我们将定义间隔的半径,这需要使用绝对值函数:

from sqlalchemy import func

class Interval(object):
    # ...

    @hybrid_property
    def radius(self):
        return abs(self.length) / 2

    @radius.expression
    def radius(cls):
        return func.abs(cls.length) / 2

在python函数之上 abs() 用于实例级操作,SQL函数 ABS() 是通过 func 类级表达式的对象::

>>> i1.radius
2

>>> print(Session().query(Interval).filter(Interval.radius > 5))
SELECT interval.id AS interval_id, interval.start AS interval_start,
    interval."end" AS interval_end
FROM interval
WHERE abs(interval."end" - interval.start) / :abs_1 > :param_1

注解

当为混合属性或方法定义表达式时,表达式方法 must 保留原始混合的名称,否则具有附加状态的新混合将附加到具有不匹配名称的类。要使用上面的示例:

class Interval(object):
    # ...

    @hybrid_property
    def radius(self):
        return abs(self.length) / 2

    # WRONG - the non-matching name will cause this function to be
    # ignored
    @radius.expression
    def radius_expression(cls):
        return func.abs(cls.length) / 2

这对于其他的变异器方法也是如此,例如 hybrid_property.update_expression() . 这和 @property 构造它是标准python的一部分。

定义setter

混合属性还可以定义setter方法。如果我们想要 length 上面,设置后修改端点值:

class Interval(object):
    # ...

    @hybrid_property
    def length(self):
        return self.end - self.start

    @length.setter
    def length(self, value):
        self.end = self.start + value

这个 length(self, value) 方法现在在set:上调用:

>>> i1 = Interval(5, 10)
>>> i1.length
5
>>> i1.length = 12
>>> i1.end
17

允许批量更新ORM

当使用 Query.update() 方法,允许在update的set子句中使用混合。

通常,当使用混合动力 Query.update() ,SQL表达式用作作为集合目标的列。如果我们 Interval 班上有一辆混合动力车 start_point 链接到 Interval.start ,可直接替换为:

session.query(Interval).update({Interval.start_point: 10})

但是,当使用类似 Interval.length ,此混合表示多个列。我们可以设置一个处理程序来容纳传递给 Query.update() 可能会影响这一点,使用 hybrid_property.update_expression() 装饰者。与setter类似的处理程序是:

class Interval(object):
    # ...

    @hybrid_property
    def length(self):
        return self.end - self.start

    @length.setter
    def length(self, value):
        self.end = self.start + value

    @length.update_expression
    def length(cls, value):
        return [
            (cls.end, cls.start + value)
        ]

上面,如果我们使用 Interval.length 在更新表达式中作为:

session.query(Interval).update(
    {Interval.length: 25}, synchronize_session='fetch')

我们将得到一个更新语句,其行如下:

UPDATE interval SET end=start + :value

在某些情况下,默认的“evaluate”策略不能在python中执行集合表达式;虽然支持上面使用的addition操作符,但是对于更复杂的集合表达式,通常需要使用“fetch”或错误的同步策略,如上图所示。

注解

要使ORM批量更新与混合一起使用,混合的函数名必须与访问它的方式相匹配。这样的事情不会奏效的::

    class Interval(object):
        # ...

        def _get(self):
            return self.end - self.start

        def _set(self, value):
            self.end = self.start + value

        def _update_expr(cls, value):
            return [
                (cls.end, cls.start + value)
            ]

        length = hybrid_property(
            fget=_get, fset=_set, update_expr=_update_expr
        )

The Python descriptor protocol does not provide any reliable way for
a descriptor to know what attribute name it was accessed as, and
the UPDATE scheme currently relies upon being able to access the
attribute from an instance by name in order to perform the instance
synchronization step.

1.2 新版功能: 增加了对混合属性批量更新的支持。

处理关系

与基于列的数据相比,创建与相关对象一起工作的混合对象没有本质的区别。对不同表达式的需求往往更大。我们将说明的两种变体是“依赖连接”的混合体和“相关子查询”的混合体。

连接依赖关系混合

考虑下面的声明性映射,它与 User 到A SavingsAccount ::

from sqlalchemy import Column, Integer, ForeignKey, Numeric, String
from sqlalchemy.orm import relationship
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.ext.hybrid import hybrid_property

Base = declarative_base()

class SavingsAccount(Base):
    __tablename__ = 'account'
    id = Column(Integer, primary_key=True)
    user_id = Column(Integer, ForeignKey('user.id'), nullable=False)
    balance = Column(Numeric(15, 5))

class User(Base):
    __tablename__ = 'user'
    id = Column(Integer, primary_key=True)
    name = Column(String(100), nullable=False)

    accounts = relationship("SavingsAccount", backref="owner")

    @hybrid_property
    def balance(self):
        if self.accounts:
            return self.accounts[0].balance
        else:
            return None

    @balance.setter
    def balance(self, value):
        if not self.accounts:
            account = Account(owner=self)
        else:
            account = self.accounts[0]
        account.balance = value

    @balance.expression
    def balance(cls):
        return SavingsAccount.balance

上述混合性质 balance 与第一个 SavingsAccount 此用户的帐户列表中的条目。在python中getter/setter方法可以处理 accounts 作为上提供的python列表 self .

但是,在表达式级别,应该 User 类将在适当的上下文中使用,以便 SavingsAccount 将出席:

>>> print(Session().query(User, User.balance).
...       join(User.accounts).filter(User.balance > 5000))
SELECT "user".id AS user_id, "user".name AS user_name,
account.balance AS account_balance
FROM "user" JOIN account ON "user".id = account.user_id
WHERE account.balance > :balance_1

但是请注意,尽管实例级访问器需要担心 self.accounts 即使存在,这个问题在SQL表达式级别上也表现得不同,我们基本上会使用外部联接:

>>> from sqlalchemy import or_
>>> print (Session().query(User, User.balance).outerjoin(User.accounts).
...         filter(or_(User.balance < 5000, User.balance == None)))
SELECT "user".id AS user_id, "user".name AS user_name,
account.balance AS account_balance
FROM "user" LEFT OUTER JOIN account ON "user".id = account.user_id
WHERE account.balance <  :balance_1 OR account.balance IS NULL

关联子查询关系混合

当然,我们可以放弃依赖于封闭查询对联接的使用,转而使用相关子查询,而关联子查询可以移植地打包到单个列表达式中。关联子查询更易于移植,但在SQL级别通常执行得更差。使用相同的技术,如 使用列属性 我们可以调整 SavingsAccount 汇总余额的示例 all 帐户,并对列表达式使用相关的子查询::

from sqlalchemy import Column, Integer, ForeignKey, Numeric, String
from sqlalchemy.orm import relationship
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.ext.hybrid import hybrid_property
from sqlalchemy import select, func

Base = declarative_base()

class SavingsAccount(Base):
    __tablename__ = 'account'
    id = Column(Integer, primary_key=True)
    user_id = Column(Integer, ForeignKey('user.id'), nullable=False)
    balance = Column(Numeric(15, 5))

class User(Base):
    __tablename__ = 'user'
    id = Column(Integer, primary_key=True)
    name = Column(String(100), nullable=False)

    accounts = relationship("SavingsAccount", backref="owner")

    @hybrid_property
    def balance(self):
        return sum(acc.balance for acc in self.accounts)

    @balance.expression
    def balance(cls):
        return select(func.sum(SavingsAccount.balance)).\
                where(SavingsAccount.user_id==cls.id).\
                label('total_balance')

上面的食谱会给我们 balance 呈现相关选择的列:

>>> print(s.query(User).filter(User.balance > 400))
SELECT "user".id AS user_id, "user".name AS user_name
FROM "user"
WHERE (SELECT sum(account.balance) AS sum_1
FROM account
WHERE account.user_id = "user".id) > :param_1

构建自定义比较器

Hybrid属性还包括一个助手,它允许构建自定义比较器。Comparator对象允许您分别自定义每个SQLAlchemy表达式运算符的行为。它们在创建自定义类型时非常有用,这些自定义类型在SQL端具有一些非常特殊的行为。

注解

这个 hybrid_property.comparator() 本节介绍的装饰器 替换 使用的 hybrid_property.expression() 装饰者。它们不能一起使用。

下面的示例类允许对名为 word_insensitive ::

from sqlalchemy.ext.hybrid import Comparator, hybrid_property
from sqlalchemy import func, Column, Integer, String
from sqlalchemy.orm import Session
from sqlalchemy.ext.declarative import declarative_base

Base = declarative_base()

class CaseInsensitiveComparator(Comparator):
    def __eq__(self, other):
        return func.lower(self.__clause_element__()) == func.lower(other)

class SearchWord(Base):
    __tablename__ = 'searchword'
    id = Column(Integer, primary_key=True)
    word = Column(String(255), nullable=False)

    @hybrid_property
    def word_insensitive(self):
        return self.word.lower()

    @word_insensitive.comparator
    def word_insensitive(cls):
        return CaseInsensitiveComparator(cls.word)

上面的SQL表达式 word_insensitive 将应用 LOWER() 两边的SQL函数:

>>> print(Session().query(SearchWord).filter_by(word_insensitive="Trucks"))
SELECT searchword.id AS searchword_id, searchword.word AS searchword_word
FROM searchword
WHERE lower(searchword.word) = lower(:lower_1)

这个 CaseInsensitiveComparator 上面实现了 ColumnOperators 接口。“强制”操作(如lowercasing)可应用于所有比较操作(即 eqltgt 等)使用 Operators.operate() ::

class CaseInsensitiveComparator(Comparator):
    def operate(self, op, other):
        return op(func.lower(self.__clause_element__()), func.lower(other))

跨子类重用混合属性

一个混合可以从一个超类中引用,以允许修改诸如 hybrid_property.getter()hybrid_property.setter() 用于在子类上重新定义这些方法。这类似于标准的python @property 对象作品:

class FirstNameOnly(Base):
    # ...

    first_name = Column(String)

    @hybrid_property
    def name(self):
        return self.first_name

    @name.setter
    def name(self, value):
        self.first_name = value

class FirstNameLastName(FirstNameOnly):
    # ...

    last_name = Column(String)

    @FirstNameOnly.name.getter
    def name(self):
        return self.first_name + ' ' + self.last_name

    @name.setter
    def name(self, value):
        self.first_name, self.last_name = value.split(' ', 1)

上面, FirstNameLastName 类是指来自 FirstNameOnly.name 为子类重新调整getter和setter的用途。

当超越 hybrid_property.expression()hybrid_property.comparator() 作为对超类的第一个引用,这些名称与类级别上相同的命名访问器冲突 QueryableAttribute 对象在类级别返回。要在直接引用父类描述符时重写这些方法,请添加特殊限定符 hybrid_property.overrides ,它会将插入指令的属性反引用回混合对象::

class FirstNameLastName(FirstNameOnly):
    # ...

    last_name = Column(String)

    @FirstNameOnly.name.overrides.expression
    def name(cls):
        return func.concat(cls.first_name, ' ', cls.last_name)

1.2 新版功能: 补充 hybrid_property.getter() 以及根据子类重新定义访问器的能力。

混合值对象

注意在前面的示例中,如果要比较 word_insensitive 的属性 SearchWord 实例到一个普通的python字符串,普通的python字符串不会被强制为小写- CaseInsensitiveComparator 我们建造,由 @word_insensitive.comparator ,仅适用于SQL端。

自定义比较器的一种更全面的形式是构造 混合值对象 . 此技术将目标值或表达式应用于值对象,然后由访问器在所有情况下返回该对象。Value对象允许控制对该值的所有操作,以及如何处理比较值,包括在SQL表达式端和Python值端。替换上一个 CaseInsensitiveComparator 用新的 CaseInsensitiveWord 班级:

class CaseInsensitiveWord(Comparator):
    "Hybrid value representing a lower case representation of a word."

    def __init__(self, word):
        if isinstance(word, basestring):
            self.word = word.lower()
        elif isinstance(word, CaseInsensitiveWord):
            self.word = word.word
        else:
            self.word = func.lower(word)

    def operate(self, op, other):
        if not isinstance(other, CaseInsensitiveWord):
            other = CaseInsensitiveWord(other)
        return op(self.word, other.word)

    def __clause_element__(self):
        return self.word

    def __str__(self):
        return self.word

    key = 'word'
    "Label to apply to Query tuple results"

上面, CaseInsensitiveWord 对象表示 self.word ,可以是SQL函数,也可以是Python本机函数。压倒一切 operate()__clause_element__() 在…方面工作 self.word ,所有比较操作都将针对 word ,无论是SQL端还是Python端。我们的 SearchWord 现在可以交付 CaseInsensitiveWord 从单个混合调用中无条件获取对象::

class SearchWord(Base):
    __tablename__ = 'searchword'
    id = Column(Integer, primary_key=True)
    word = Column(String(255), nullable=False)

    @hybrid_property
    def word_insensitive(self):
        return CaseInsensitiveWord(self.word)

这个 word_insensitive 属性现在普遍具有不区分大小写的比较行为,包括SQL表达式与Python表达式(注意,这里的python值被转换为小写):

>>> print(Session().query(SearchWord).filter_by(word_insensitive="Trucks"))
SELECT searchword.id AS searchword_id, searchword.word AS searchword_word
FROM searchword
WHERE lower(searchword.word) = :lower_1

SQL表达式与SQL表达式:

>>> sw1 = aliased(SearchWord)
>>> sw2 = aliased(SearchWord)
>>> print(Session().query(
...                    sw1.word_insensitive,
...                    sw2.word_insensitive).\
...                        filter(
...                            sw1.word_insensitive > sw2.word_insensitive
...                        ))
SELECT lower(searchword_1.word) AS lower_1,
lower(searchword_2.word) AS lower_2
FROM searchword AS searchword_1, searchword AS searchword_2
WHERE lower(searchword_1.word) > lower(searchword_2.word)

仅限python表达式::

>>> ws1 = SearchWord(word="SomeWord")
>>> ws1.word_insensitive == "sOmEwOrD"
True
>>> ws1.word_insensitive == "XOmEwOrX"
False
>>> print(ws1.word_insensitive)
someword

混合值模式对于任何可能具有多种表示形式的值都非常有用,例如时间戳、时间增量、度量单位、货币和加密密码。

参见

Hybrids and Value Agnostic Types -在techpot.zzzeek.org博客上

Value Agnostic Types, Part II -在techpot.zzzeek.org博客上

建筑变压器

A 变压器 是一个可以接收 Query 对象并返回新的。这个 Query 对象包含一个方法 with_transformation() 它返回一个新的 Query 由给定函数转换。

我们可以把这个和 Comparator 类来生成一种类型的配方,既可以设置查询的FROM子句,也可以指定筛选条件。

考虑映射类 Node ,它使用邻接列表组装成层次树模式:

from sqlalchemy import Column, Integer, ForeignKey
from sqlalchemy.orm import relationship
from sqlalchemy.ext.declarative import declarative_base
Base = declarative_base()

class Node(Base):
    __tablename__ = 'node'
    id = Column(Integer, primary_key=True)
    parent_id = Column(Integer, ForeignKey('node.id'))
    parent = relationship("Node", remote_side=id)

假设我们想添加一个访问器 grandparent . 这将返回 parent 属于 Node.parent . 当我们有一个 Node ,这很简单:

from sqlalchemy.ext.hybrid import hybrid_property

class Node(Base):
    # ...

    @hybrid_property
    def grandparent(self):
        return self.parent.parent

在表达上,事情并不那么清楚。我们需要建造一个 Query 我们在哪里 Query.join() 两次沿着 Node.parent 到达 grandparent . 我们可以返回一个转换可调用文件,并将其与 Comparator 类接收任何 Query 对象,并返回一个新的 Node.parent 属性并根据给定条件进行筛选:

from sqlalchemy.ext.hybrid import Comparator

class GrandparentTransformer(Comparator):
    def operate(self, op, other):
        def transform(q):
            cls = self.__clause_element__()
            parent_alias = aliased(cls)
            return q.join(parent_alias, cls.parent).\
                        filter(op(parent_alias.parent, other))
        return transform

Base = declarative_base()

class Node(Base):
    __tablename__ = 'node'
    id = Column(Integer, primary_key=True)
    parent_id = Column(Integer, ForeignKey('node.id'))
    parent = relationship("Node", remote_side=id)

    @hybrid_property
    def grandparent(self):
        return self.parent.parent

    @grandparent.comparator
    def grandparent(cls):
        return GrandparentTransformer(cls)

这个 GrandparentTransformer 超越核心 Operators.operate() 方法的基础 Comparator 返回查询转换可调用的层次结构,然后在特定上下文中运行给定的比较操作。例如,在上面的示例中, operate 方法被调用,给定 Operators.eq 可调用以及比较的右侧 Node(id=5) . 函数 transform 然后返回,它将转换 Query 第一个加入 Node.parent ,然后比较 parent_alias 使用 Operators.eq 向左右两侧传球 Query.filter()

>>> from sqlalchemy.orm import Session
>>> session = Session()
sql>>> session.query(Node).\
...        with_transformation(Node.grandparent==Node(id=5)).\
...        all()

我们可以通过将“join”步骤与“filter”步骤分离,将模式修改为更详细但更灵活。这里棘手的部分是确保 GrandparentTransformer 使用相同的 AliasedClass 反对对象 Node . 下面我们使用一种简单的记忆方法,将 GrandparentTransformer 每节课:

class Node(Base):

    # ...

    @grandparent.comparator
    def grandparent(cls):
        # memoize a GrandparentTransformer
        # per class
        if '_gp' not in cls.__dict__:
            cls._gp = GrandparentTransformer(cls)
        return cls._gp

class GrandparentTransformer(Comparator):

    def __init__(self, cls):
        self.parent_alias = aliased(cls)

    @property
    def join(self):
        def go(q):
            return q.join(self.parent_alias, Node.parent)
        return go

    def operate(self, op, other):
        return op(self.parent_alias.parent, other)
sql>>> session.query(Node).\
...            with_transformation(Node.grandparent.join).\
...            filter(Node.grandparent==Node(id=5))

“Transformer”模式是一种实验模式,它开始使用一些函数式编程模式。虽然它只推荐给高级和/或病患开发人员,但可能有很多神奇的东西可以使用。

API引用

Object Name Description

Comparator

允许轻松构造自定义 PropComparator 用于混血儿的类。

hybrid_method

一个允许定义具有实例级和类级行为的Python对象方法的修饰器。

HYBRID_METHOD

符号表示 InspectionAttr 那是类型的 hybrid_method .

hybrid_property

允许定义具有实例级和类级行为的python描述符的修饰器。

HYBRID_PROPERTY

class sqlalchemy.ext.hybrid.hybrid_method(func, expr=None)

一个允许定义具有实例级和类级行为的Python对象方法的修饰器。

method sqlalchemy.ext.hybrid.hybrid_method.__init__(func, expr=None)

创建新的 hybrid_method .

通常通过装饰器使用:

from sqlalchemy.ext.hybrid import hybrid_method

class SomeClass(object):
    @hybrid_method
    def value(self, x, y):
        return self._value + x + y

    @value.expression
    def value(self, x, y):
        return func.some_function(self._value, x, y)
method sqlalchemy.ext.hybrid.hybrid_method.expression(expr)

提供定义SQL表达式生成方法的修改修饰符。

attribute sqlalchemy.ext.hybrid.hybrid_method.extension_type = symbol('HYBRID_METHOD')

分机类型(如果有)。默认为 NOT_EXTENSION

class sqlalchemy.ext.hybrid.hybrid_property(fget, fset=None, fdel=None, expr=None, custom_comparator=None, update_expr=None)

允许定义具有实例级和类级行为的python描述符的修饰器。

method sqlalchemy.ext.hybrid.hybrid_property.__init__(fget, fset=None, fdel=None, expr=None, custom_comparator=None, update_expr=None)

创建新的 hybrid_property .

通常通过装饰器使用:

from sqlalchemy.ext.hybrid import hybrid_property

class SomeClass(object):
    @hybrid_property
    def value(self):
        return self._value

    @value.setter
    def value(self, value):
        self._value = value
method sqlalchemy.ext.hybrid.hybrid_property.comparator(comparator)

提供定义自定义比较器生成方法的修改修饰器。

修饰方法的返回值应该是 Comparator .

注解

这个 hybrid_property.comparator() decorator 替换 使用的 hybrid_property.expression() 装饰者。它们不能一起使用。

当在类级别调用混合时, Comparator 这里给出的对象被包装在一个专用的 QueryableAttribute ,这是ORM用来表示其他映射属性的同一类对象。这样做的原因是,可以在返回的结构中维护其他类级属性(如docstrings和对混合体本身的引用),而不必修改传入的原始comparator对象。

注解

当提到一个拥有类的混合财产时(例如。 SomeClass.some_hybrid )的实例 QueryableAttribute 返回,将表达式或比较器对象表示为此混合对象。但是,该对象本身具有调用的访问器 expressioncomparator ;因此,当尝试在子类上重写这些修饰符时,可能需要使用 hybrid_property.overrides 先修改。有关详细信息,请参阅该修饰符。

method sqlalchemy.ext.hybrid.hybrid_property.deleter(fdel)

提供定义删除方法的修改修饰符。

method sqlalchemy.ext.hybrid.hybrid_property.expression(expr)

提供定义SQL表达式生成方法的修改修饰符。

当在类级别调用混合时,此处给出的SQL表达式包装在专用的 QueryableAttribute ,这是ORM用来表示其他映射属性的同一类对象。这样做的原因是,可以在返回的结构中维护其他类级属性(如docstrings和对混合体本身的引用),而不修改传入的原始SQL表达式。

注解

当提到一个拥有类的混合财产时(例如。 SomeClass.some_hybrid )的实例 QueryableAttribute 返回,表示表达式或比较器对象以及此混合对象。但是,该对象本身具有调用的访问器 expressioncomparator ;因此,当尝试在子类上重写这些修饰符时,可能需要使用 hybrid_property.overrides 先修改。有关详细信息,请参阅该修饰符。

attribute sqlalchemy.ext.hybrid.hybrid_property.extension_type = symbol('HYBRID_PROPERTY')

分机类型(如果有)。默认为 NOT_EXTENSION

method sqlalchemy.ext.hybrid.hybrid_property.getter(fget)

提供定义getter方法的修改修饰符。

1.2 新版功能.

attribute sqlalchemy.ext.hybrid.hybrid_property.overrides

覆盖现有属性的方法的前缀。

这个 hybrid_property.overrides 访问器只返回这个混合对象,当从父类的类级别调用这个混合对象时,它将取消引用通常在此级别返回的“instructed attribute”,并允许修改类似 hybrid_property.expression()hybrid_property.comparator() 在不与通常存在于 QueryableAttribute ::

class SuperClass(object):
    # ...

    @hybrid_property
    def foobar(self):
        return self._foobar

class SubClass(SuperClass):
    # ...

    @SuperClass.foobar.overrides.expression
    def foobar(cls):
        return func.subfoobar(self._foobar)

1.2 新版功能.

method sqlalchemy.ext.hybrid.hybrid_property.setter(fset)

提供定义setter方法的修改修饰符。

method sqlalchemy.ext.hybrid.hybrid_property.update_expression(meth)

提供定义更新元组生成方法的修改修饰符。

方法接受单个值,该值是要呈现到UPDATE语句的SET子句中的值。然后,该方法应将该值处理为适合于ultimate set子句的单个列表达式,并将其作为2元组序列返回。每个元组都包含一个列表达式作为键和一个要呈现的值。

例如。::

class Person(Base):
    # ...

    first_name = Column(String)
    last_name = Column(String)

    @hybrid_property
    def fullname(self):
        return first_name + " " + last_name

    @fullname.update_expression
    def fullname(cls, value):
        fname, lname = value.split(" ", 1)
        return [
            (cls.first_name, fname),
            (cls.last_name, lname)
        ]

1.2 新版功能.

class sqlalchemy.ext.hybrid.Comparator(expression)

允许轻松构造自定义 PropComparator 用于混血儿的类。

sqlalchemy.ext.hybrid.HYBRID_METHOD = symbol('HYBRID_METHOD')

符号表示 InspectionAttr 那是类型的 hybrid_method .

分配给 InspectionAttr.extension_type 属性。

参见

Mapper.all_orm_attributes

sqlalchemy.ext.hybrid.HYBRID_PROPERTY = symbol('HYBRID_PROPERTY')
符号表示 InspectionAttr 那是

类型的 hybrid_method .

分配给 InspectionAttr.extension_type 属性。

参见

Mapper.all_orm_attributes

Previous: 水平切分 Next: 可转位的