[英]How can SQLAlchemy association_proxy be used bi-directionally?
[英]How to do a case-insensitive query for sqlalchemy association_proxy attributes?
我有两个课程,一个曲目和一个专辑。 为了从曲目轻松访问专辑字段,我创建了一个关联代理。
class Track(MusicItem, Base):
__tablename__ = "tracks"
_id = Column(Integer, primary_key=True)
_album_id = Column(Integer, ForeignKey("albums._id"))
artist = Column(String, nullable=False, default="")
path = Column(_PathType, nullable=False, unique=True)
title = Column(String, nullable=False, default="")
_album_obj = relationship("Album", back_populates="tracks")
album = association_proxy('_album_obj', 'title')
class Album(MusicItem, Base):
__tablename__ = "albums"
_id = Column(Integer, primary_key=True)
artist = Column(String, nullable=False, default="")
title = Column(String, nullable=False, default="")
tracks = relationship("Track", back_populates="_album_obj", cascade="all, delete")
但是,我在尝试对曲目或专辑进行不区分大小写的查询时遇到问题。
创建查询过滤器时,以下内容适用于轨道的正常(非关联代理)属性。
attr = getattr(Track, field)
attr = sqlalchemy.func.lower(attr)
但是,当attr
是关联代理属性时,会出现以下错误:
moe/core/query.py:187: in query
items = session.query(query_cls).filter(*query_filters).all()
.venv/lib/python3.8/site-packages/sqlalchemy/orm/query.py:3346: in all
return list(self)
.venv/lib/python3.8/site-packages/sqlalchemy/orm/query.py:3508: in __iter__
return self._execute_and_instances(context)
.venv/lib/python3.8/site-packages/sqlalchemy/orm/query.py:3533: in _execute_and_instances
result = conn.execute(querycontext.statement, self._params)
.venv/lib/python3.8/site-packages/sqlalchemy/engine/base.py:1011: in execute
return meth(self, multiparams, params)
.venv/lib/python3.8/site-packages/sqlalchemy/sql/elements.py:298: in _execute_on_connection
return connection._execute_clauseelement(self, multiparams, params)
.venv/lib/python3.8/site-packages/sqlalchemy/engine/base.py:1124: in _execute_clauseelement
ret = self._execute_context(
.venv/lib/python3.8/site-packages/sqlalchemy/engine/base.py:1316: in _execute_context
self._handle_dbapi_exception(
.venv/lib/python3.8/site-packages/sqlalchemy/engine/base.py:1510: in _handle_dbapi_exception
util.raise_(
.venv/lib/python3.8/site-packages/sqlalchemy/util/compat.py:182: in raise_
raise exception
.venv/lib/python3.8/site-packages/sqlalchemy/engine/base.py:1276: in _execute_context
self.dialect.do_execute(
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <sqlalchemy.dialects.sqlite.pysqlite.SQLiteDialect_pysqlite object at 0x7f54a0692430>
cursor = <sqlite3.Cursor object at 0x7f54a0638b90>
statement = 'SELECT tracks._id AS tracks__id, tracks._album_id AS tracks__album_id, tracks.artist AS tracks_artist, tracks.path AS tracks_path, tracks.title AS tracks_title \nFROM tracks \nWHERE lower(?) = ?'
parameters = (ColumnAssociationProxyInstance(AssociationProxy('_album_obj', 'title')), 'tmp')
context = <sqlalchemy.dialects.sqlite.base.SQLiteExecutionContext object at 0x7f54a05b7fa0>
def do_execute(self, cursor, statement, parameters, context=None):
> cursor.execute(statement, parameters)
E sqlalchemy.exc.InterfaceError: (sqlite3.InterfaceError) Error binding parameter 0 - probably unsupported type.
E [SQL: SELECT tracks._id AS tracks__id, tracks._album_id AS tracks__album_id, tracks.artist AS tracks_artist, tracks.path AS tracks_path, tracks.title AS tracks_title
E FROM tracks
E WHERE lower(?) = ?]
E [parameters: (ColumnAssociationProxyInstance(AssociationProxy('_album_obj', 'title')), 'tmp')]
E (Background on this error at: http://sqlalche.me/e/13/rvf5)
.venv/lib/python3.8/site-packages/sqlalchemy/engine/default.py:593: InterfaceError
不确定是否有帮助,但这里有一些关于查询的更简化的代码。 如果需要,我可以对此进行扩展。
query_filters = [attr == query_value]
items = session.query(Track).filter(*query_filters).all()
我也在创建自定义比较器的文档中看到了这个相关的部分,但我不知道如何将它应用到我的代码中。 我将它与 Track/Album 类一起添加,但它没有任何帮助,并且发生了相同的错误。
从 1.3.19 版开始,sqlalchemy 不允许将 SQL 函数应用于关联代理属性。 这是一个跟踪该问题的问题。
对于不区分大小写查找的具体情况,可以使用ilike()
session.query(Track).filter(somecolumn.ilike("value"))
ilike()
适用于关联代理属性和普通属性。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.