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)


Представляете, какой 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

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