python - 混合属性的过滤器计算结果为 "where false"

标签 python sqlalchemy

我设置了一个映射...

from sqlalchemy import Column, Integer, String
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import Session
from sqlalchemy.ext.hybrid import hybrid_property

Base = declarative_base()

class Chap(Base):
    __tablename__ = 'chap'

    id = Column(Integer, primary_key=True)
    tophats = Column(Integer)
    exclamation = Column(String)

    @hybrid_property
    def hat_brag(self):
        return "I have "+str(self.tophats)+" tophats!"

    @hybrid_property
    def cold_complain(self):
        return self.exclamation+", it's cold!"

...我创造了一个小伙子。

>>>c1 = Chap(tophats=5, exclamation="Blimey")

现在我想根据他提示天气的方式来查询这个人:

>>>print(Session().query(Chap).filter(Chap.cold_complain == "Blimey, it's cold!"))
SELECT chap.id AS chap_id, chap.tophats AS chap_tophats, chap.gloves AS chap_gloves, chap.exclamation AS chap_exclamation 
FROM chap 
WHERE chap.exclamation || :exclamation_1 = :param_1

那个 SQL 代码看起来是正确的,但现在我想在另一个 hybrid_property 上查询他,一个包含转换为 strint...

>>>print(Session().query(Chap).filter(Chap.hat_brag == "I have 5 tophats!"))
SELECT chap.id AS chap_id, chap.tophats AS chap_tophats, chap.exclamation AS chap_exclamation 
FROM chap 
WHERE false

哪里是假的。这看起来不像是正确的查询!有人知道这是怎么回事吗?

最佳答案

在查询中,SQLAlchemy 将使用没有专用 @...expression() method 的混合属性的 getter 方法生成用于查询的必要 SQL 对象。 getter 方法绑定(bind)到,而不是实例,所以self在这种情况下将引用您的 Chap类。

为您的cold_complain属性,即 Chap.exclamation + ", it's cold!"返回,导致 chap.exclamation || :exclamation_1 SQL表达式; +转换为 SQL 连接运算符。

但是对于你的hat_brag属性返回一个字符串;执行的表达式实际上是 "I have "+str(Chap.tophats)+" tophats!" , 变成 'I have Chap.tophats tophats!' :

>>> "I have "+str(Chap.tophats)+" tophats!"
'I have Chap.tophats tophats!'

这是一个固定的静态字符串。接下来,这是您过滤器的一部分,带有 == "I have 5 tophats!" .这两个静态字符串值不相等:

>>> "I have "+str(Chap.tophats)+" tophats!" == "I have 5 tophats!"
False

这就是发送到数据库的 SQL 查询中使用的内容。

您在这里要做的是使用 expression() option并定义查询的 SQL 友好版本:

from sqlalchemy.sql.expression import cast

class Chap(Base):
    # ...

    @hybrid_property
    def hat_brag(self):
        return "I have "+str(self.tophats)+" tophats!"

    @hat_brag.expression
    def hat_brag(cls):
        return "I have " + cast(cls.tophats, String) + " tophats!"

现在 expression方法用于查询,实例上的原始函数,在 Python 中:

>>> c1.hat_brag
'I have 5 tophats!'
>>> print(Session().query(Chap).filter(Chap.hat_brag == "I have 5 tophats!"))
SELECT chap.id AS chap_id, chap.tophats AS chap_tophats, chap.exclamation AS chap_exclamation
FROM chap
WHERE :param_1 || CAST(chap.tophats AS VARCHAR) || :param_2 = :param_3

关于python - 混合属性的过滤器计算结果为 "where false",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54487741/

相关文章:

python - 旧版本的 spaCy 在尝试安装模型时抛出 "KeyError: ' 包'"错误

python - 新手 Django 模型错误

flask - 在 Flask-sqlalchemy 中获取排序结果

python - alembic:在迁移中使用子查询更新语句

sql-server - 将存储过程选择结果读入 pandas 数据帧

python - 基于条件的子字符串替换-python

python - 从 Python 脚本调用 Pyramid View

python - 如何使用Python的Request包访问API Get的特定元素?

python - SQLAlchemy 继承阻止创建基础实例

python - 如何使用 sqlalchemy 有效地管理频繁的模式更改?