2009-05-28 6 views
6

私はちょうどsqlalchemyを持つCRMアプリケーションからかなり厄介なスキーマをイントロスペクトしました。すべてのテーブルに削除された列があり、それらのエンティティとリレーションシップのすべてを自動的にフィルタリングして、削除済みとしてフラグを付けたかったのです。ここに私が思い付いたものです:SQLAlchemyクエリを自動的にフィルタリングする正しい方法はありますか?


class CustomizableQuery(Query): 
    """An overridden sqlalchemy.orm.query.Query to filter entities 

    Filters itself by BinaryExpressions 
    found in :attr:`CONDITIONS` 
    """ 

    CONDITIONS = [] 

    def __init__(self, mapper, session=None): 
     super(CustomizableQuery, self).__init__(mapper, session) 
     for cond in self.CONDITIONS: 
      self._add_criterion(cond) 

    def _add_criterion(self, criterion): 
     criterion = self._adapt_clause(criterion, False, True) 
     if self._criterion is not None: 
      self._criterion = self._criterion & criterion 
     else: 
      self._criterion = criterion 

そして、それはこのように使われています:

class UndeletedContactQuery(CustomizableQuery): 
    CONDITIONS = [contacts.c.deleted != True] 

    def by_email(self, email_address): 
     return EmailInfo.query.by_module_and_address('Contacts', email_address).contact 

    def by_username(self, uname): 
     return self.filter_by(twod_username_c=uname).one() 

class Contact(object): 
    query = session.query_property(UndeletedContactQuery) 

Contact.query.by_email('[email protected]') 

EmailInfoは、電子メールや、彼らがしている他のモジュール間の結合テーブルにマップされていますクラスでありますに関連する。

は、ここでは、マッパーの例です:これは私がすべて削除された連絡先を除外したことで欲しいものを私に与え

contacts_map = mapper(Contact, join(contacts, contacts_cstm), { 
    '_emails': dynamic_loader(EmailInfo, 
           foreign_keys=[email_join.c.bean_id], 
           primaryjoin=contacts.c.id==email_join.c.bean_id, 
           query_class=EmailInfoQuery), 
    }) 

class EmailInfoQuery(CustomizableQuery): 

    CONDITIONS = [email_join.c.deleted != True] 
    # More methods here 

。私も自分のマッパーでdynamic_loaderするQUERY_CLASS引数としてこれを使用することができます - しかし...

  1. がこれを行うには良い方法がありますが、私はcompicatedクラスの内部でチャンスをうかがっには本当に満足していません私のような質問があります。
  2. 誰かが共有できる別の方法でこれを解決しましたか?

答えて

7

selectにマップすることができます。このように:

mapper(EmailInfo, select([email_join], email_join.c.deleted == False)) 
+0

非常にいいです、私はそれについて知りませんでした! –

+0

私はこれを(別のテーブルで)しようとしましたが、うまくいかなかったのです。私は得ました: TypeError: 'テーブル'オブジェクトは反復可能ではありません 何が良いのでしょうか? –

+0

私の悪い、選択する最初のパラメータは、オブジェクトのような列/テーブルのリストですので、email_joinはリストになければなりません。私はそれを修正します。 –

0

私は削除された要素をフィルタリングこれらのテーブルのビューを作成することができたならば見て検討したい、とあなたが代わりに基礎となる表のビューに直接マップすることができるかもしれません、少なくともクエリ操作のために。しかし、私はこれを自分で試したことはありません!

関連する問題