У меня есть класс пользователя, в котором хранится столбец «first_name» и столбец «псевдоним», чтобы описать имя человека и его псевдоним. Я хочу, чтобы иметь возможность запросить этот класс, чтобы найти пользователей, либо их first_name или их псевдонима, поэтому я написал свой класс так:SQLAlchemy: Как я могу создать гибридное свойство для дизъюнкции столбцов?
from sqlalchemy import Column, Integer, String, create_engine, orm
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.ext.hybrid import hybrid_property
engine = create_engine('sqlite:///:memory:')
Base = declarative_base()
Session = orm.sessionmaker(engine)
class User(Base):
__tablename__ = 'user'
id = Column(Integer, primary_key=True)
first_name = Column(String(64))
alias = Column(String(64), nullable=True)
@hybrid_property
def name(self):
return self.alias or self.first_name
def __repr__(self):
return 'User("{}" a.k.a. "{}")'.format(self.first_name, self.alias)
if __name__ == "__main__":
Base.metadata.create_all(engine)
Это почти работает. Я могу искать пользователей по их имени. Но я не могу искать пользователей по их псевдонимам.
>>> session = Session()
>>> user = User(first_name="Edward", alias="Ed")
>>> session.add(user)
>>> session.flush()
>>> session.query(User).filter_by(name="Edward").first()
User("Edward" a.k.a. "Ed")
>>> session.query(User).filter_by(name="Ed").first()
>>>
Это делает sense-- выражений, генерируемых name
не те, которые я хочу.
>>> print session.query(User).filter_by(name="Ed")
SELECT "user".id AS user_id, "user".first_name AS user_first_name, "user".alias AS user_alias
FROM "user"
WHERE "user".first_name = :first_name_1
SQLAlchemy docs on hybrid properties, кажется, предлагает решение использовать hybrid_property.expression() изменить сгенерированный выражение. Однако я не могу понять, какое выражение имеет смысл вернуться.
Моя первая идея состояла в том, чтобы вернуть своего рода OR
:
from sqlalchemy.sql import or_
@name.expression
def name(cls):
return or_(cls.first_name, cls.alias)
Но выражения, которые он генерирует предсказуемо неправильно:
SELECT "user".id AS user_id, "user".first_name AS user_first_name, "user".alias AS user_alias
FROM "user"
WHERE ("user".first_name OR "user".alias) = :param_1
Как я могу сделать эту работу?