Python SQLAlchemy:按关系中的关系字段排序
在我正在开发的金字塔应用程序中,我有以下场景:Python SQLAlchemy:按关系中的关系字段排序,python,sqlalchemy,pyramid,Python,Sqlalchemy,Pyramid,在我正在开发的金字塔应用程序中,我有以下场景: class Widget(Base): __tablename__ = 'widgets' id = Column(Integer, primary_key=True) name = Column(String(50)) sidebar = Column(mysql.TINYINT(2)) def __init__(self, name, sidebar): self.name = name
class Widget(Base):
__tablename__ = 'widgets'
id = Column(Integer, primary_key=True)
name = Column(String(50))
sidebar = Column(mysql.TINYINT(2))
def __init__(self, name, sidebar):
self.name = name
self.sidebar = sidebar
class Dashboard(Base):
__tablename__ = 'dashboard'
user_id = Column(Integer, ForeignKey('users.id'), primary_key=True)
widget_id = Column(Integer, ForeignKey('widgets.id'), primary_key=True)
delta = Column(mysql.TINYINT)
widget = relationship('Widget')
def __init__(self, user_id, widget_id, delta):
self.user_id = user_id
self.widget_id = widget_id
self.delta = delta
class User(Base):
__tablename__ = 'users'
id = Column(Integer, primary_key=True)
login = Column(Unicode(255), unique=True)
password = Column(Unicode(60))
fullname = Column(Unicode(100))
dashboard = relationship('Dashboard', order_by='Dashboard.widget.sidebar, Dashboard.delta')
def __init__(self, login, password, fullname):
self.login = login
self.password = crypt.encode(password)
self.fullname = fullname
因此,我希望用户“dashboard”关系具有用户的仪表板记录,但按dashboard的关系属性“sidebar”排序。目前我遇到以下错误:
sqlalchemy.exc.InvalidRequestError: Property 'widget' is not an instance of ColumnProperty (i.e. does not correspond directly to a Column).
在关系声明中可以进行这种排序吗
谢谢 这样,试着想想当SQLAlchemy尝试加载User.dashboard时应该发出什么样的SQLAlchemy。像从仪表板连接小部件中选择*。。。按widget.sidebar订购?或者从仪表板顺序中选择*通过从小部件中选择侧栏?按不同的表对结果进行排序对于关系来说太过开放,无法自行决定。实现这一点的方法是,当ORM针对仪表板的表发出简单的SELECT时,以及当ORM在一个不太简单的SELECT中引用它时,在仪表板中提供一个列表达式,该表达式可以提供这种排序,其中ORM可以一次跨用户、仪表板表连接,例如,即时加载 我们提供自定义SQL表达式,特别是那些涉及其他表的SQL表达式,当我们不希望在默认情况下加载该表达式时,可以使用,也可以使用。例如:
from sqlalchemy import *
from sqlalchemy.orm import *
from sqlalchemy.ext.declarative import declarative_base
Base = declarative_base()
class Widget(Base):
__tablename__ = 'widgets'
id = Column(Integer, primary_key=True)
name = Column(String(50))
sidebar = Column(Integer)
class Dashboard(Base):
__tablename__ = 'dashboard'
user_id = Column(Integer, ForeignKey('users.id'), primary_key=True)
widget_id = Column(Integer, ForeignKey('widgets.id'), primary_key=True)
delta = Column(Integer)
widget = relationship('Widget')
widget_sidebar = deferred(select([Widget.sidebar]).where(Widget.id == widget_id))
class User(Base):
__tablename__ = 'users'
id = Column(Integer, primary_key=True)
login = Column(Unicode(255), unique=True)
dashboard = relationship('Dashboard', order_by='Dashboard.widget_sidebar, Dashboard.delta')
e = create_engine("sqlite://", echo=True)
Base.metadata.create_all(e)
s = Session(e)
w1, w2 = Widget(name='w1', sidebar=1), Widget(name='w2', sidebar=2)
s.add_all([
User(login='u1', dashboard=[
Dashboard(
delta=1, widget=w1
),
Dashboard(
delta=2, widget=w2
)
]),
])
s.commit()
print s.query(User).first().dashboard
加载.dashboard发出的最终SQL是:
SELECT dashboard.user_id AS dashboard_user_id, dashboard.widget_id AS dashboard_widget_id, dashboard.delta AS dashboard_delta
FROM dashboard
WHERE ? = dashboard.user_id ORDER BY (SELECT widgets.sidebar
FROM widgets
WHERE widgets.id = dashboard.widget_id), dashboard.delta
请记住,MySQL在优化上述子查询方面做得很糟糕。如果在这里需要高性能,可以考虑将侧栏的值复制到仪表板中,即使这使得一致性更难维护。