在具有Indexable
类型的列上定义具有“索引”属性的ORM映射类上的属性。
“index”表示该属性与具有预定义索引的Indexable
列的元素相关联以访问它。Indexable
类型包括ARRAY
,JSON
和HSTORE
等类型。
The indexable
extension provides Column
-like interface for any element of an Indexable
typed column. 在简单的情况下,它可以被视为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'
这些属性也可以在课堂上进行访问。下面,我们举例说明用于生成索引SQL标准的Person.name
:
>>> 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
includes special behaviors for when the indexed data structure does not exist, and a set operation is called:
index_property
,默认数据结构将是None
值的Python列表,至少与索引值一样长;该值将被设置在列表中的位置。这意味着对于索引值为零的列表,在设置给定值之前,列表将初始化为[None]
,对于索引值5,列表将初始化为设置前设为[无, 无, 无, 无, 无]
给定值的第五个元素。请注意,现有的列表不是扩展到位以接收值。index_property
,Python字典将用作默认数据结构。index_property.datatype
参数将默认数据结构设置为可调用的任何Python,覆盖以前的规则。index_property
can be subclassed, in particular for the common use case of providing coercion of values or SQL expressions as they are accessed. 下面是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特定版本的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
sqlalchemy.ext.indexable.
index_property
(attr_name, index, datatype=None, mutable=True, onebased=True)¶基础:sqlalchemy.ext.hybrid.hybrid_property
属性生成器。生成的属性描述对应于Indexable
列的对象属性。
版本1.1中的新功能
__init__
(attr_name, index, datatype=None, mutable=True, onebased=True)¶创建一个新的index_property
。
参数: |
|
---|