views:

39

answers:

3

I'm using pylons with sqlalchemy. I have several models, and found myself wrote such code again and again:

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()

Since the models are all extend class Base, is there any way to define a common get_by_id() method?

So I can use it as:

quesiton = Question.get_by_id(question_id)
answer = Answer.get_by_id(answer_id)
...
user = User.get_by_id(user_id)
A: 
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)
Aaron Gallagher
I believe the `Base` that Freewind was referring to is the result of calling `declarative_base`, so its definition isn't available for direct modification this way.
dhaffey
@dhaffey, so, as I already said, don't use `declarative`. Wooooooo.
Aaron Gallagher
@Aaron, I don't understand, why you said `declarative` silly?
Freewind
@Freewind, `declarative` mashes together the database schema, relations, and mapped object all into one hideous amalgamation. This leads to a number of problems with varying degrees of hacky workarounds, not to mention a large amount of excess magic in places where it's not necessary.
Aaron Gallagher
+2  A: 

Unfortunately, SQLAlchemy doesn't allow you to subclass Base without a corresponding table declaration. You could define a mixin class with get_by_id as a classmethod, but then you'd need to specify it for each class.

A quicker-and-dirtier solution is to just monkey-patch it into 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)

This assumes you've got a session object available at definition-time, otherwise you'll need to pass it as an argument each time.

dhaffey
This is only true if you're using the silly `declarative` stuff. The easiest fix is to not use `declarative`.
Aaron Gallagher
@dhaffey, thank you very much, it works well :)
Freewind
This answer helped me with a related problem I was having. Thanks.
Sean M
+1  A: 

If id is your primary key column, you just do:

session.query(Foo).get(id)

which has the advantage of not querying the database if that instance is already in the session.

avdd
@avdd, thank you, it's really important
Freewind