用于字符串的SQLAlchemy hybrid_property怎么了?

时间:2019-02-01 22:04:21

标签: 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上查询他,该属性包含一个int转换为str ...

>>>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

错误的地方。那看起来不像是正确的查询!有人知道怎么回事吗?

1 个答案:

答案 0 :(得分:1)

在查询中,SQLAlchemy将使用混合属性的getter方法(不带专用的@...expression() method)来生成用于查询的必要SQL对象。该吸气剂的方法被结合到,而不是一个实例,因此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