Release: 1.4.0b1 | Release Date: November 2, 2020

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表达式机制进行计算时,该参数返回新的SQL表达式::

>>> print(Interval.length)
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”或错误的同步策略,如上图所示。

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 -在techspot.zzzeek.org博客上

Value Agnostic Types, Part II -在techspot.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对象方法的修饰器。

类签名

class sqlalchemy.ext.hybrid.hybrid_method (sqlalchemy.orm.base.InspectionAttrInfo)

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表达式生成方法的修改修饰符。

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

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

类签名

class sqlalchemy.ext.hybrid.hybrid_property (sqlalchemy.orm.base.InspectionAttrInfo)

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 先修改。有关详细信息,请参阅该修饰符。

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: 可转位的