2013-04-10 11 views
17

クエリオブジェクトにカスタムメソッドを作成して、このようなことを行う方法はありますか? all_active()は、本質的に.filter(User.is_active == True)SQLAlchemy - クエリオブジェクトにカスタムメソッドを追加できますか?

あり、それのオフフィルタすることができ

User.query.all_active() 

User.query.all_active().filter(User.age == 30) 
+0

私はこの他[質問/解答](http://stackoverflow.com/questions/7604967/に疑問sqlalchemy-build-query-filter-dynamic-from-dict)はこれに任意の用途がありますか? (これはカスタムメソッドの数が減っていますが、カスタムダイナミックフィルタの数は増えています) – summea

答えて

33

あなたがあなた自身のメソッドを追加するために基本Queryクラスをサブクラス化することができます

from sqlalchemy.orm import Query 

class MyQuery(Query): 

    def all_active(self): 
    return self.filter(User.is_active == True) 

あなたは、あなたがセッション(docs here)を作成するときに、この新しいクエリクラスを使用するSQLAlchemyのを教えてください。あなたのコードからは、フラスコSQLAlchemyのを使用している場合がありますように見えますので、次のようにあなたはそれを行うだろう:

db = SQLAlchemy(session_options={'query_cls': MyQuery}) 

は、そうしないと、sessionmakerに直接引数を渡すことになります。

sessionmaker(bind=engine, query_cls=MyQuery) 

右のとおり現在、この新しいクエリオブジェクトは、メソッド内にUserクラスをハードコードしたので興味深いわけではないので、他のものでは機能しません。より良い実装では、クエリの基底クラスを使用して、適用するフィルタを決定します。これは少しトリッキーですが、同様に行うことができます(あなたがいずれかを持っている場合)

class MyOtherQuery(Query): 

    def _get_models(self): 
    """Returns the query's underlying model classes.""" 
    if hasattr(query, 'attr'): 
     # we are dealing with a subquery 
     return [query.attr.target_mapper] 
    else: 
     return [ 
     d['expr'].class_ 
     for d in query.column_descriptions 
     if isinstance(d['expr'], Mapper) 
     ] 

    def all_active(self): 
    model_class = self._get_models()[0] 
    return self.filter(model_class.is_active == True) 

は最後に、この新しいクエリクラスは動的な関係で使用されることはありません。あなたが関係を作成するときに引数として渡すことができ、それらはまた、それを使用できるようにするには:どちらかといえば

users = relationship(..., query_class=MyOtherQuery) 
+0

これは私にとっては役に立ちません。 https://gist.github.com/nickretallack/76bcd65cc0305abcd33b –

+1

@NickRetallack私はBaseModelクラスを作成し、query_classクラス属性を宣言することで成功しました。しかし、これは問題のようです:https://github.com/mitsuhiko/flask-sqlalchemy/blob/fe67c633f2e6d66a01a1670e5fc6649506358d20/flask_sqlalchemy/__init__.py#L737 – justanr

+0

あなたは1つのセッションが1つのクエリクラスでしか動作できないと言います。私たちはもっとうまくできますか?同じセッションで動的にクエリクラスを選択できるようにしますか?私は、異なるテーブルが異なるクエリクラスを持つことができることを意味しますが、同じセッションでそれらを使用することができます(たとえば、1つのトランザクションで使用する場合など)。 – Mahdi

関連する問題