gpt4 book ai didi

python - SQLAlchemy:按关系中的关系字段排序

转载 作者:太空狗 更新时间:2023-10-30 01:22:44 24 4
gpt4 key购买 nike

在我正在处理的 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
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

因此,我希望用户“仪表板”关系具有用户的仪表板记录,但按“侧边栏”(这是仪表板的关系属性)排序。目前我收到此错误:

sqlalchemy.exc.InvalidRequestError: Property 'widget' is not an instance of ColumnProperty (i.e. does not correspond directly to a Column).

这种排序在关系声明中可能吗?

谢谢!

最佳答案

有了这个,试着想一想 SQLAlchemy 在尝试加载 User.dashboard 时应该发出什么。喜欢 SELECT * FROM dashboard JOIN widget ... ORDER BY widget.sidebar 吗?或者 SELECT * FROM dashboard ORDER BY (SELECT sidebar FROM widget... ?用不同的表排序结果对于 relationship() 来说太开放了自己决定。完成此操作的方法是根据 Dashboard 提供列表达式,当 ORM 发出针对仪表板表的简单 SELECT 时,以及它何时在不太简单的 SELECT 中引用它,它可能会同时跨用户、仪表板表加入(例如,预先加载)。

我们使用 column_property() 提供自定义 SQL 表达式,尤其是那些涉及其他表的表达式,或者使用 deferred()当我们不希望默认加载该表达式时(这里很可能就是这种情况)。示例:

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 对上述子查询的优化工作很糟糕。如果您在这里需要高性能,您可能会考虑将“sidebar”的值复制到“dashboard”中,即使这会使一致性更难维护。

关于python - SQLAlchemy:按关系中的关系字段排序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19569448/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com