2009-05-28 74 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

我会考虑看是否有可能创建视图这些表是过滤掉删除的元素,然后你可能能够直接映射到该视图的基础表的替代,至少用于查询操作。但我从来没有尝试过这个自己!