Я использую пилоны с sqlalchemy. У меня есть несколько моделей, и я обнаружил, что написал такой код снова и снова:
question = Session.query(Question).filter_by(id=question_id).one()
answer = Session.query(Answer).fileter_by(id=answer_id).one()
...
user = Session.query(User).filter_by(id=user_id).one()
Так как все модели расширяются, класс Base
, есть ли способ определить общий метод get_by_id()
?
Поэтому я могу использовать его как:
quesiton = Question.get_by_id(question_id)
answer = Answer.get_by_id(answer_id)
...
user = User.get_by_id(user_id)
К сожалению, SQLAlchemy не позволяет подклассифицировать Base
без соответствующего объявления таблицы. Вы можете определить класс mixin с get_by_id
как метод класса, но тогда вам нужно будет указать его для каждого класса.
Более быстрое и грязное решение состоит в том, чтобы просто обезглавить его в Base
:
def get_by_id(cls, id, session=session):
return session.query(cls).filter_by(id=id).one()
Base.get_by_id = classmethod(get_by_id)
Это предполагает, что у вас есть объект session
, доступный во время определения, в противном случае вам нужно будет передавать его как аргумент каждый раз.
Если id
- ваш столбец первичного ключа, вы просто выполните:
session.query(Foo).get(id)
который имеет то преимущество, что не запрашивает базу данных, если этот экземпляр уже находится в сеансе.
class Base(object):
@classmethod
def get_by_id(cls, session, id):
q = session.query(cls).filter_by(id=id)
return q.one()
Question.get_by_id(Session, question_id)
Base
которую ссылался Freewind, является результатом вызова declarative_base
, поэтому ее определение недоступно для прямого изменения таким способом.
declarative
. Wooooooo.
declarative
вещи. Самый простой способ - не использоватьdeclarative
.