Что происходит с SQLAlchemy hybrid_property для строк? - PullRequest
0 голосов
/ 02 февраля 2019

Я настроил отображение ...

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 выглядит правильно, но теперь я хочу запросить его о другом гибридном свойстве, которое содержит 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 голосов
/ 02 февраля 2019

В запросе SQLAlchemy будет использовать метод получения гибридного свойства без выделенного @...expression() метода для создания необходимых объектов 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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...