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

Я использую декларативную базу 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() может помочь, но я не смог найти ни одного примера, показывающего компаратор, который ссылается на другой столбец таблицы.

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


person amercader    schedule 19.01.2011    source источник


Ответы (2)


arrow_upward
4
arrow_downward

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

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

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

person 9000    schedule 19.01.2011
comment
Спасибо, теперь я вижу, что должен попробовать другой подход. - person amercader; 20.01.2011

arrow_upward
10
arrow_downward

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

person marcinkuzminski    schedule 01.10.2011
comment
Можно ли привести пример того, как использовать это для замены строки, как указано выше? Я получаю такие вещи, как TypeError: expected string or buffer и AttributeError: Neither 'InstrumentedAttribute' object nor 'Comparator' object associated with Entry.page_title has an attribute 'partition', но я пытаюсь обрабатывать свои объекты page_title как строку, которую, как я вижу, это не так... Хотя я не уверен, как получить строковое значение. - person hello-klol; 19.03.2014