python - 如何使用sqlalchemy的hybrid_property查询多个字段?

标签 python sqlalchemy

我的模型定义如下:

class Patch(Base):
    id = Column(Integer, primary_key=True)
    major = Column(Integer, nullable=False)
    minor = Column(Integer, nullable=False)

    @hybrid_property
    def patch(self) -> str:
        return f'{self.major}.{self.minor}'

    @patch.expression
    def patch(self):
        return func.concat(self.major, '.', self.minor)

我想提出此类请求:

Patch.query.order_by(Patch.patch)

这应该等于接下来的 SQL 命令:

SELECT * FROM patch ORDER BY major DESC, minor DESC

我尝试使用 hybrid_property.expression

    @patch.expression
    def patch(self):
        return self.major, self.minor

但出现异常:

sqlalchemy.exc.InvalidRequestError: SQL expression, column, or mapped entity expected - got '(<sqlalchemy.orm.attributes.InstrumentedAttribute object at 0x7f1a5cd5fc50>, <sqlalchemy.orm.attributes.InstrumentedAttribute object at 0x7f1a5cd5fd00>)

我知道可以使用custrom comparator ,但我还没有找到如何使用两个字段(即 majorminor )来做到这一点。

有什么想法吗?

附注它不一定是hybrid_property ,无论哪种方式都可以

最佳答案

下面的内容适用于两个单独字段的排序。值得注意的是,patch 的 Python 实现仍然是一个字符串,因此 Python 对象和 SQL 行之间的排序会有所不同,除非您更改 patch 以返回 (major ,次要)。使用 Python 3.6.5、SQLAlchemy 1.1.15、psycopg2 2.7.7 进行测试

from sqlalchemy import create_engine, Column, Integer, func
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.ext.hybrid import hybrid_property
from sqlalchemy.orm import sessionmaker
from sqlalchemy.sql.functions import concat

engine = create_engine('postgresql://localhost:5432/postgres', echo=True)
Base = declarative_base(bind=engine)


class Patch(Base):

    __tablename__ = "patch"

    id = Column(Integer, primary_key=True)
    major = Column(Integer, nullable=False)
    minor = Column(Integer, nullable=False)

    @hybrid_property
    def patch(self) -> str:
        return f'{self.major}.{self.minor}'

    @patch.expression
    def patch(self):
        return self.major.op(",")(self.minor)

    def __repr__(self):
        return f"Patch object {self.id} {self.patch}"


Base.metadata.create_all()
Session = sessionmaker(bind=engine)
session = Session()

if __name__ == "__main__":
    if session.query(Patch).count() == 0:
        example_patches = [Patch(major=major, minor=minor) for major in range(3) for minor in range(3)]
        session.add_all(example_patches)
        session.commit()

    patches = session.query(Patch).order_by(Patch.patch).all()
    print(patches)
2019-06-13 14:44:27,245 INFO sqlalchemy.engine.base.Engine SELECT patch.id AS patch_id, patch.major AS patch_major, patch.minor AS patch_minor 
  FROM patch ORDER BY patch.major , patch.minor
2019-06-13 14:44:27,245 INFO sqlalchemy.engine.base.Engine {}
[Patch object 2740 0.0, Patch object 2741 0.1, Patch object 2742 0.2, Patch object 2743 0.3, Patch object 2744 0.4, Patch object 2745 0.5, Patch object 2746 0.6, Patch object 2747 0.7, Patch object 2748 0.8, Patch object 2749 0.9, Patch object 2750 0.10, ...

关于python - 如何使用sqlalchemy的hybrid_property查询多个字段?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56576308/

相关文章:

python - Excel 日期到 Python 并返回到 excel

c++ - 在 C++/STL 中是否有与 Python range() 等效的紧凑函数

python - 使用 sqlalchemy 的 row_to_json 语法

python - 如何在Python Flask中实现帖子的点赞按钮功能?

python - 使用 python、sqlalchemy 和 psycopg2 创建 PostgreSQL 数据库时出错

python - 用于 SQL Alchemy 的 Py3k MySQL 驱动程序

python - MiniBatchKMeans.fit 和 MiniBatchKMeans.partial_fit 之间的区别

python - 将来自循环的多个线程排队的最安全方法是什么?

python - 如何正确转换列表的输出值以将它们用作函数内的参数?

python - 如何使用 Sqlalchemy 根据计算出的 json 值选择 Postgresql 记录?