2010-09-03 71 views
1

我正在用sqlalchemy使用掛架。我有幾種模式,並發現自己一次又一次地寫了這樣的代碼:如何爲Sqlalchemy中的各種模型編寫通用的get_by_id()方法?

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) 

回答

2

不幸的是,SQLAlchemy的不允許子類Base沒有相應的表聲明。你可以用get_by_id定義mixin class作爲classmethod,但是你需要爲每個類指定它。

一個更快的,和骯髒的解決方案是隻猴子補丁成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對象,否則你將需要通過它每次都是一個爭論。

+0

這隻有在你使用愚蠢的'聲明性'材料時纔是正確的。最簡單的解決方法是不使用'declarative'。 – habnabit 2010-09-03 18:36:52

+0

非常感謝你,它效果不錯:) – Freewind 2010-09-04 05:25:33

+0

這個答案幫助我解決了我遇到的一個相關問題。謝謝。 – 2010-10-27 16:41:01

0
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) 
+0

我相信Freewind提到的'Base'是調用'declarative_base'的結果,所以它的定義不可用於直接修改。 – dhaffey 2010-09-03 18:26:35

+0

@dhaffey,所以,正如我已經說過的,不要使用'declarative'。 Wooooooo。 – habnabit 2010-09-03 18:41:40

+0

我不明白,爲什麼你說'陳述性'愚蠢? – Freewind 2010-09-04 05:26:07

3

如果id是你的主鍵列,你只是做:

session.query(Foo).get(id) 

其中有如果這個實例已經在會議上沒有查詢數據庫的優勢。

+0

謝謝,這真的很重要 – Freewind 2010-09-04 06:19:56

相關問題