从SQLAlchemy文档中的many-to-many relationship example开始,我想添加一个属性first_child
,它将返回由关系定义的children
的第一个子节点。 first_child
属性需要在association_proxy
属性定义中使用,例如下面的first_child_id
。
from sqlalchemy import Table, Column, Integer, ForeignKey
from sqlalchemy.ext.associationproxy import association_proxy
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import relationship
Base = declarative_base()
association_table = Table('association', Base.metadata,
Column('left_id', Integer, ForeignKey('left.id')),
Column('right_id', Integer, ForeignKey('right.id'))
)
class Parent(Base):
__tablename__ = 'left'
id = Column(Integer, primary_key=True)
children = relationship("Child", secondary=association_table)
first_child = ???
first_child_id = association_proxy('first_child', 'id')
class Child(Base):
__tablename__ = 'right'
id = Column(Integer, primary_key=True)
我认为我需要将first_child
声明为hybrid_property
or a column_property
,但我不知道如何返回第一个元素。
除了first_child
之外,我还需要last_child
和相关的last_child_id
属性。
我正在使用SQLAlchemy和MySQL数据库。
答案 0 :(得分:0)
如果你需要的是最小start_time 和最大end_time ,那么我只会为这些列使用column_property
:
association_table = Table(
'association', Base.metadata,
Column('left_id', Integer, ForeignKey('left.id')),
Column('right_id', Integer, ForeignKey('right.id'))
)
class Child(Base):
__tablename__ = 'right'
id = Column(Integer, primary_key=True)
start_time = Column(DateTime)
end_time = Column(DateTime)
class Parent(Base):
__tablename__ = 'left'
id = Column(Integer, primary_key=True)
children = relationship(
"Child",
secondary=association_table,
backref="parents",
)
min_start_time = column_property(
select([Child.start_time.label("min_start_time")])
.where(Child.id == association_table.c.right_id)
.where(id == association_table.c.left_id)
.order_by(Child.start_time.asc())
.limit(1)
)
max_end_time = column_property(
select([Child.end_time.label("max_end_time")])
.where(Child.id == association_table.c.right_id)
.where(id == association_table.c.left_id)
.order_by(Child.end_time.desc())
.limit(1)
.as_scalar()
)
但是如果您需要关系中不止一个这样的特殊列,那么使用hybrid_property
可能会更有效。
答案 1 :(得分:0)
association_proxy
的问题在于您不能在 hybrid_properties
上使用它(或者至少不能直接使用)。
一个简单的解决方案可能是使用 property
装饰器,它会在已经加载的实例上进行评估:
class Parent(Base):
__tablename__ = 'left'
id = Column(Integer, primary_key=True)
children = relationship("Child", secondary=association_table)
@property
def first_child(self):
return children[0]
但是,您将无法在查询中使用它,并且它是“只读”属性。有关 SQLAlchemy plain-descriptor 的更多信息。