Bezdepbonusu7Программирование: статьи и ответы

Вопрос

SQLAlchemy: запрашивать настраиваемое свойство на основе поля таблицы

Автор вопроса: amercaderОтветов: 2

Я использую декларативную базу SQLAlchemy для определения моей модели. Я определил свойство name, которое вычисляется из одного столбца (title):

class Entry(Base):
    __tablename__ = "blog_entry"
    id = Column(Integer, primary_key=True)
    title = Column(Unicode(255))
    ...

    @property
    def name(self):
        return re.sub(r'[^a-zA-Z0-9 ]','',self.title).replace(' ','-').lower()

При попытке выполнить запрос с использованием name SQLAlchemy выдает ошибку:

Session.query(Entry).filter(Entry.name == my_name).first()
>>> ArgumentError: filter() argument must be of type sqlalchemy.sql.ClauseElement or string

После некоторого исследования я обнаружил, что, возможно, comparable_using() может помочь, но я не смог найти ни одного примера, показывающего компаратор, который ссылается на другой столбец таблицы.

Это вообще возможно или есть лучший подход?

pythonsqlalchemy

Ответы

Ответ 1 · рейтинг 4 · 9000

Представляете, какой SQL должен быть выдан на ваш запрос? База данных ничего не знает о name, у нее нет ни способа его вычислить, ни использовать какой-либо индекс для ускорения поиска.

Мой лучший выбор - это полное сканирование, выборка title для каждой записи, вычисление name, а затем фильтрация по ней. Вы можете грубо сделать это [x for x in Session.query(Entry).all() if x.name==my_name][0]. Немного усложнившись, вы получите только id и title на проходе фильтрации, а затем получите полные записи на id.

Обратите внимание, что полное сканирование обычно не очень хорошо с точки зрения производительности, если только ваша таблица не очень маленькая.

Ответ 2 · рейтинг 10 · marcinkuzminski

Из SqlAlchemy 0.7 вы можете добиться этого с помощью hybrid_property, см. документы здесь: http://www.sqlalchemy.org/docs/orm/extensions/hybrid.html

Перевод вопроса и ответов сообщества Stack Overflow, лицензия CC BY-SA. Оригинал на Stack Overflow.

Похожие материалы