在我的应用程序中,我有这样的模型:
class A(Base):
id = Column(UUID, primary_key=True)
name_a = Column(Text)
class B(Base):
id = Column(UUID, primary_key=True)
name_b = Column(Text)
parent_a_id = Column(UUID, ForeignKey(A.id))
parent_a = relationship(A, lazy='joined')
class C(Base):
id = Column(UUID, primary_key=True)
name_c = Column(Text)
parent_b_id = Column(UUID, ForeignKey(B.id))
parent_b = relationship(B, lazy='joined')
当我这样做时:
DBSession().query(C).all()
它工作正常 - 我在一个LEFT OUTER JOIN查询中得到所有带有B和A名称的C名称。
但我想知道如何通过以下方式按排序 name_a,name_b,name_c ?
我正在尝试做类似的事情:
DBSession().query(C).order_by(
C.parent_b.parent_a.name_a,
C.parent_b.name_b,
C.name_c
).all()
此类代码不起作用。如何用sqlalchemy精神来完成它?
答案 0 :(得分:2)
我玩了你的样本并使用PostgreSQL来增加积分。
您的查询返回C对象列表,传统上在SQL中,您只能按检索的列进行排序。在幕后检索关系,所以我不明白为什么应该可以按它们排序。
从好的方面来说,一旦检索到列表,它就会在你的内存中附带整个层次结构,因此你可以超快速地在内存中对它进行排序:
clist = session.query(C).all()
sorted(clist, key=lambda c:(c.b.a.name, c.b.name, c.name))
我找到的另一个解决方案是对parameter
使用order_by relationship
:
class B(Base):
...
a = relationship(A, order_by="A.name", lazy='joined')
class C(Base):
...
b = relationship(B, order_by="B.name", lazy='joined')
最终结果:
print (session.query(C).order_by(C.name) )
ORDER BY tc.name,tb_1.name,ta_1.name
这与你想要的很接近,但你需要反转列表才能按A.name, B.name, C.name
顺序获得它。
P.S。:我的确切类定义供参考:
#!/usr/bin/env python
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import Column, Integer, ForeignKey, create_engine, Text
from sqlalchemy.orm import relationship
engine_connect_str = "postgresql://postgres@MYSERV/mydb"
engine = create_engine(engine_connect_str, echo=False)
Session = sessionmaker(engine)
session = Session()
Base = declarative_base()
class A(Base):
__tablename__ = 'ta'
id = Column('id', Integer, primary_key=True)
name = Column(Text)
def __repr__(self):
return "{}(id={}, name='{}')".format(self.__class__.__name__, self.id, self.name)
class B(Base):
__tablename__ = 'tb'
id = Column('id', Integer,primary_key=True)
name = Column(Text)
a_id = Column('aid', ForeignKey(A.id), nullable=False)
a = relationship(A, order_by="A.name", lazy='joined')
def __repr__(self):
return "{}(id={}, name='{}', a_id={})".format(self.__class__.__name__, self.id, self.name, self.a_id)
class C(Base):
__tablename__ = 'tc'
id = Column('id', Integer, primary_key=True)
name = Column(Text)
b_id = Column('bid', ForeignKey(B.id), nullable=False)
b = relationship(B, order_by="B.name", lazy='joined')
def __repr__(self):
return "{}(id={}, name='{}', b_id={})".format(self.__class__.__name__, self.id, self.name, self.b_id)