版本:1.1.0b2 |发布日期:2016年7月1日

SQLAlchemy 1.1文档

可转位¶ T0>

在具有Indexable类型的列上定义具有“index”属性的ORM映射类上的属性。

“index”表示该属性与一个带有预定义索引的Indexable列的元素相关联以访问它。Indexable类型包括ARRAYJSONHSTORE等类型。

The indexable extension provides Column-like interface for any element of an Indexable typed column. 在简单情况下,可以将其视为Column映​​射的属性。

版本1.1中的新功能

概要¶ T0>

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列表,至少与索引值一样长;该值将被设置在列表中的位置。This means for an index value of zero, the list will be initalized to [None] before setting the given value, and for an index value of five, the list will be initialized to [None, None, None, None, None] before setting the fifth element to the given value. 请注意,现有的列表不是扩展到接收值。
  • 对于给定任何其他类型的索引值(例如字符串)的index_property,Python字典将用作默认数据结构。
  • 可以使用index_property.datatype参数将默认数据结构设置为可调用的任何Python,覆盖以前的规则。

子类¶ T0>

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)

The age attribute at the instance level works as before; however when rendering SQL, Postgresql’s ->> operator will be used for indexed access, instead of the usual index opearator of ->:

>>> 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(attr_name, index, datatype=None, mutable=True, onebased=True)

Bases: sqlalchemy.ext.hybrid.hybrid_property

属性生成器。生成的属性描述对应于Indexable列的对象属性。

版本1.1中的新功能

__init__(attr_name, index, datatype=None, mutable=True, onebased=True)

创建一个新的index_property

参数:
  • attr_name – An attribute name of an Indexable typed column, or other attribute that returns an indexable structure.
  • index – The index to be used for getting and setting this value. 这应该是整数的Python端索引值。
  • 数据类型 - 字段为空时使用的缺省数据类型。默认情况下,这是从使用的索引类型派生的;一个整数索引的Python列表,或任何其他风格的索引的Python字典。对于列表,列表将被初始化为至少index个元素的无值列表。
  • mutable – if False, writes and deletes to the attribute will be disallowed.
  • onebased – assume the SQL representation of this value is one-based; that is, the first index in SQL is 1, not zero.