SQLAlchemy 2.0 文档
可索引¶
在 ORM 映射类上定义具有“索引”属性的属性,这些属性对应于具有 Indexable
类型的列。
“索引”表示该属性与具有预定义索引的 Indexable
列的元素相关联。 Indexable
类型包括 ARRAY
、JSON
和 HSTORE
等类型。
indexable
扩展为 Column
-like 接口提供 Indexable
类型列的任何元素。在简单情况下,可以将其视为 Column
- 映射属性。
概述¶
假设 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
,默认数据结构将是 Python 列表,包含至少与索引值一样多的None
值;然后在列表中设置该值。这意味着对于索引值为零,列表将在设置给定值之前初始化为[None]
,而对于索引值为五,列表将在设置第五个元素为给定值之前初始化为[None, None, None, None, None]
。请注意,现有的列表不会在原处扩展以接收一个值。对于给定任何其他类型索引值(例如通常为字符串)的
index_property
,Python 字典用作默认数据结构。可以使用
index_property.datatype
参数将默认数据结构设置为任何 Python 可调用对象,从而覆盖前面的规则。
子类化¶
index_property
可以子类化,特别是对于提供值或 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 参考¶
对象名称 | 描述 |
---|---|
属性生成器。生成的属性描述一个对象属性,该属性对应于一个 |
- class sqlalchemy.ext.indexable.index_property¶
属性生成器。生成的属性描述一个对象属性,该属性对应于一个
Indexable
列。成员
-
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 侧的索引值。
default¶ – 当给定索引处没有值时,将返回一个值,而不是 AttributeError。
datatype¶ – 当字段为空时使用的默认数据类型。默认情况下,此类型是从所用索引类型推断出来的;对于整数索引,Python 列表,对于其他类型的索引,Python 字典。对于列表,该列表将初始化为至少
index
个元素长的 None 值列表。mutable¶ – 如果为 False,将不允许对属性进行写入和删除。
onebased¶ – 假设此值的 SQL 表示形式是以 1 为基的;也就是说,SQL 中的第一个索引是 1,而不是 0。
-
method
flambé! the dragon and The Alchemist image designs created and generously donated by Rotem Yaari.
Created using Sphinx 7.2.6. Documentation last generated: Fri 08 Nov 2024 08:41:19 AM EST