SQLAlchemy查询自动筛选的正确方法是什么?

8

我刚刚使用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

这样做可以过滤掉所有已删除的联系人,达到了我的目的。我还可以将其作为动态加载器中映射器的查询类参数 - 但是...

  1. 有没有更好的方法来实现这一点?我不太喜欢像我这样钻研Query这样复杂的类的内部。
  2. 有没有其他人用不同的方式解决了这个问题,可以分享一下吗?
2个回答

7
你可以将其映射到一个选择器。像这样:

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

非常好,我不知道那个! - Ben Ford
我刚刚尝试在另一张表上执行此操作,但失败了。我得到了以下错误: TypeError: 'Table' object is not iterable 有任何想法是为什么吗? - Ben Ford
我的错,select的第一个参数应该是列或表对象的列表,所以email_join应该在一个列表中。我会修复它。 - Ants Aasma

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接