可转位的

优质
小牛编辑
132浏览
2023-12-01

在ORM映射类上定义属性,这些类对具有 Indexable 类型。

“索引”是指属性与 Indexable 带有预定义索引的列以访问它。这个 Indexable 类型包括类型,例如 ARRAYJSONHSTORE .

这个 indexable 扩展提供 Column -类似于任何元素的接口 Indexable 类型化列。在简单的情况下,它可以被视为 Column -映射的属性。

1.1 新版功能.

简介

鉴于 Person 作为具有主键和JSON数据字段的模型。虽然此字段中可能有任意数量的元素编码,但我们希望引用名为 name 单独作为专用属性,其行为类似于独立列:

from sqlalchemy import Column, JSON, Integer
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.ext.indexable import index_property

Base = declarative_base()

class Person(Base):
    __tablename__ = 'person'

    id = Column(Integer, primary_key=True)
    data = Column(JSON)

    name = index_property('data', 'name')

上面, name 属性现在的行为类似于映射列。我们可以组成一个新的 Person 并设置 name ::

>>> person = Person(name='Alchemist')

现在可以访问该值:

>>> person.name
'Alchemist'

在幕后,json字段被初始化为新的空白字典,字段被设置为:

>>> person.data
{"name": "Alchemist'}

字段在适当位置是可变的:

>>> person.name = 'Renamed'
>>> person.name
'Renamed'
>>> person.data
{'name': 'Renamed'}

使用时 index_property ,我们对可索引结构所做的更改也会自动跟踪为历史记录;我们不再需要使用 MutableDict 以便跟踪工作单元的此更改。

删除也可以正常工作:

>>> del person.name
>>> person.data
{}

以上,删除 person.name 从字典中删除值,但不删除字典本身。

丢失的钥匙将产生 AttributeError ::

>>> person = Person()
>>> person.name
...
AttributeError: 'name'

除非设置默认值:

>>> class Person(Base):
>>>     __tablename__ = 'person'
>>>
>>>     id = Column(Integer, primary_key=True)
>>>     data = Column(JSON)
>>>
>>>     name = index_property('data', 'name', default=None)  # See default

>>> person = Person()
>>> print(person.name)
None

属性也可以在类级别上访问。下面,我们举例说明 Person.name 用于生成索引的SQL条件::

>>> from sqlalchemy.orm import Session
>>> session = Session()
>>> query = session.query(Person).filter(Person.name == 'Alchemist')

上述查询等价于:

>>> query = session.query(Person).filter(Person.data['name'] == 'Alchemist')

倍数 index_property 可以链接对象以生成多个索引级别:

from sqlalchemy import Column, JSON, Integer
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.ext.indexable import index_property

Base = declarative_base()

class Person(Base):
    __tablename__ = 'person'

    id = Column(Integer, primary_key=True)
    data = Column(JSON)

    birthday = index_property('data', 'birthday')
    year = index_property('birthday', 'year')
    month = index_property('birthday', 'month')
    day = index_property('birthday', 'day')

上面的查询,例如:

q = session.query(Person).filter(Person.year == '1980')

在PostgreSQL后端,上述查询将呈现为:

SELECT person.id, person.data
FROM person
WHERE person.data -> %(data_1)s -> %(param_1)s = %(param_2)s

默认值

index_property 包括索引数据结构不存在时的特殊行为,并调用集合操作:

  • 对于一个 index_property 如果给定一个整数索引值,则默认的数据结构将是 None 值,至少与索引值一样长;然后在列表中的位置设置该值。这意味着对于索引值为零,列表将初始化为 [None] 在设置给定值之前,如果索引值为5,则列表将初始化为 [None, None, None, None, None] 在将第五个元素设置为给定值之前。请注意,现有列表是 not 扩展到位以接收值。

  • 对于一个 index_property 如果给定任何其他类型的索引值(例如,通常是字符串),则使用Python字典作为默认数据结构。

  • 默认数据结构可以设置为使用 index_property.datatype 参数,重写以前的规则。

子类别化

index_property 可以是子类的,特别是对于在访问值或SQL表达式时提供强制值或SQL表达式的常见用例。下面是一个与PostgreSQL JSON类型一起使用的常用方法,我们还希望在其中包括自动强制转换加 astext() ::

class pg_json_property(index_property):
    def __init__(self, attr_name, index, cast_type):
        super(pg_json_property, self).__init__(attr_name, index)
        self.cast_type = cast_type

    def expr(self, model):
        expr = super(pg_json_property, self).expr(model)
        return expr.astext.cast(self.cast_type)

上述子类可与PostgreSQL特定版本的 JSON ::

from sqlalchemy import Column, Integer
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.dialects.postgresql import JSON

Base = declarative_base()

class Person(Base):
    __tablename__ = 'person'

    id = Column(Integer, primary_key=True)
    data = Column(JSON)

    age = pg_json_property('data', 'age', Integer)

这个 age 实例级别的属性和以前一样工作;但是在呈现SQL时,PostgreSQL的 ->> 运算符将用于索引访问,而不是 -> ::

>>> query = session.query(Person).filter(Person.age < 20)

以上查询将呈现:

SELECT person.id, person.data
FROM person
WHERE CAST(person.data ->> %(data_1)s AS INTEGER) < %(param_1)s

API引用

Object NameDescription

index_property

属性生成器。生成的属性描述与 Indexable 列。

class sqlalchemy.ext.indexable.index_property(attr_name, index, default=<object object>, datatype=None, mutable=True, onebased=True)

属性生成器。生成的属性描述与 Indexable 列。

1.1 新版功能.

参见

sqlalchemy.ext.indexable

类签名

class sqlalchemy.ext.indexable.index_property (sqlalchemy.ext.hybrid.hybrid_property)

method sqlalchemy.ext.indexable.index_property.__init__(attr_name, index, default=<object object>, datatype=None, mutable=True, onebased=True)

创建新的 index_property .

参数
  • attr_name -- 属性名称 Indexable 类型化列或返回可索引结构的其他属性。

  • index -- 用于获取和设置此值的索引。这应该是整数的python-side索引值。

  • default -- 将返回的值,而不是 AttributeError 当给定索引处没有值时。

  • datatype -- 字段为空时使用的默认数据类型。默认情况下,这是从使用的索引类型派生的;整数索引的python列表,或任何其他类型索引的python字典。对于列表,该列表将初始化为一个至少为 index 元素长。

  • mutable -- 如果为false,则不允许对属性进行写入和删除。

  • onebased -- 假设此值的SQL表示形式是基于一个;即,SQL中的第一个索引是1,而不是零。