2009-05-28 30 views
6

我剛剛從CRM應用程序中用sqlalchemy回想了一個非常討厭的模式。所有的表格都有一個刪除的列,我想自動過濾所有標記爲已刪除的實體和關係。以下是我想出了:自動過濾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 

這給了我什麼,我想,我已經過濾掉所有被刪除的聯繫人。我也可以用這個作爲query_class說法在我的製圖員dynamic_loader - 但是...

  1. 有沒有更好的方式來做到這一點,我不是一個compicated類的內部打交道了真的很開心就像我一樣查詢。
  2. 有沒有人以不同的方式解決這個問題,他們可以分享?

回答

7

您可以映射到選擇。就像這樣:

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

非常好,我不知道! – 2009-05-28 13:13:45

0

我會考慮看是否有可能創建視圖這些表是過濾掉刪除的元素,然後你可能能夠直接映射到該視圖的基礎表的替代,至少用於查詢操作。但我從來沒有嘗試過這個自己!