【问题标题】:The right way to auto filter SQLAlchemy queries?自动过滤 SQLAlchemy 查询的正确方法?
【发布时间】:2010-10-29 13:48:20
【问题描述】:

我刚刚使用 sqlalchemy 从 CRM 应用程序中反省了一个非常讨厌的架构。所有表都有一个已删除的列,我想自动过滤所有标记为已删除的实体和关系。这是我想出的:


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('someone@some.com')

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. 有没有更好的方法来做到这一点,我不喜欢像我一样探索像 Query 这样的复杂类的内部结构。
  2. 有没有人以不同的方式解决了这个问题并可以分享?

【问题讨论】:

    标签: python sqlalchemy sugarcrm


    【解决方案1】:

    您可以映射到一个选择。像这样:

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

    【讨论】:

    • 很好,我不知道!
    • 我只是尝试这样做(在另一张桌子上),但没有成功。我得到了:TypeError: 'Table' object is not iterable 知道为什么吗?
    • 我的错,要选择的第一个参数是列/表类对象的列表,因此 email_join 应该在列表中。我会解决的。
    【解决方案2】:

    我会考虑看看是否可以为这些表创建视图以过滤掉已删除的元素,然后您也许可以直接映射到该视图而不是基础表,至少对于查询操作是这样。但是我自己从未尝试过!

    【讨论】:

      猜你喜欢
      • 2015-01-15
      • 2013-02-20
      • 2019-03-10
      • 1970-01-01
      • 1970-01-01
      • 2017-02-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多