如何编辑此sqlalchemy“默认”查询过滤器以使其具有优先级

时间:2019-07-03 15:19:32

标签: python sqlalchemy

编辑:我认为SQL的WHERE条件中的顺序很重要,因此也是我要求解决该问题的原因。因此,我得到了答案。

我正在尝试在sqlalchemy模型中设置默认查询过滤器,该过滤器在每次调用查询时执行。

但是问题在于它在查询的末尾添加了过滤器,这破坏了我的SQL。

是否可以使其在查询中首先过滤?

我遵循以下食谱: https://github.com/sqlalchemy/sqlalchemy/wiki/FilteredQuery

食谱中的骨架:

# see the linked web page, for full code

@event.listens_for(Query, "before_compile", retval=True)
def before_compile(query):
    for ent in query.column_descriptions:
        entity = ent['entity']
        if entity is None:
            continue
        insp = inspect(ent['entity'])
        mapper = getattr(insp, 'mapper', None)
        if mapper and issubclass(mapper.class_, HasPrivate):
            query = query.enable_assertions(False).filter(
                ent['entity'].public == True)

    return query


# this is my filter
query = query.enable_assertions(False).filter(
    ent['entity'].id != ent['entity'].other_id)

ent['entity'].id != ent['entity'].other_id放在我的SQL查询的末尾。

1 个答案:

答案 0 :(得分:1)

我认为在将过滤器添加到查询时应添加break语句,否则可能会多次在相同条件下进行过滤。

看看filter方法的internals,我看到以下代码要执行以获取条件或条件列表:

for criterion in list(criterion):
    criterion = expression._expression_literal_as_text(criterion)

    criterion = self._adapt_clause(criterion, True, True)

    if self._criterion is not None:
        self._criterion = self._criterion & criterion
    else:
        self._criterion = criterion

这意味着您可以使用以下代码添加条件:

@event.listens_for(Query, "before_compile", retval=True)
def before_compile(query):
    criterion = query._adapt_clause(criterion, True, True)
    for ent in query.column_descriptions:
        entity = ent['entity']
        if entity is None:
            continue
        insp = inspect(ent['entity'])
        mapper = getattr(insp, 'mapper', None)
        if mapper and issubclass(mapper.class_, HasPrivate):
            if query._criterion is not None:
               query._criterion = criterion & query._criterion
            else:
               query._criterion = criterion
            break
    return query