SQLAlchemy默认过滤器

Mar*_*oni 16 python sqlalchemy

我有一个带有字段is_deleted的模型,现在我希望除了传递给.filter和.filter_by的任何过滤参数之外,所有形式的查询都要通过is_deleted = False过滤.

在Django中,我通常会覆盖管理器并添加自己的过滤,但我需要SQLAlchemy的帮助.

更新:

我最终做了以下事情:

class CustomQuery(Query):
    def __new__(cls, *args, **kwargs):
        if args and hasattr(args[0][0], "is_deleted"):
            return Query(*args, **kwargs).filter_by(is_deleted=False)
        else:
            return object.__new__(cls)
session = scoped_session(sessionmaker(query_cls=CustomQuery))
Run Code Online (Sandbox Code Playgroud)

它有效,但如果我以后有更多的字段,我想我必须添加更多条件,必须有一种方法在模型级别上执行此操作.

zzz*_*eek 10

我们在https://github.com/sqlalchemy/sqlalchemy/wiki/FilteredQuery上有这个食谱

  • 是否有一种直接的方法使这个可以覆盖?这样public = True可以明确地传递给某些过滤器吗? (3认同)

mdm*_*jsh 5

这是一个非常老的问题,所以我确信 OP 解决了他们的问题,但由于它仍然没有答案(2021 年),这里是我们如何将自定义查询类应用于所有模型:

\n
    \n
  1. 如上定义自定义查询
  2. \n
\n
class CustomQuery(Query): ...\n
Run Code Online (Sandbox Code Playgroud)\n
    \n
  1. 然后将此查询类设置为基模型类的查询属性:
  2. \n
\n
class BaseModel(Model):\n    __abstract__ = True\n    query_class = CustomQuery\n    ...\n
Run Code Online (Sandbox Code Playgroud)\n

那么任何实现 BaseModel 的模型显然都会继承这个行为:

\n
class MyModel(BaseModel):\n    __tablename__ = \'my_model\' \n    ....\n\n
Run Code Online (Sandbox Code Playgroud)\n

请注意,在我们的例子中,并非所有表都遵循软删除模式(我们不关心每个表的历史记录)。在这里,您可以实现一个使用默认查询类的单独的 BaseModel。

\n
class MyModel(BaseModel):\n    __tablename__ = \'my_model\' \n    ....\n\n
Run Code Online (Sandbox Code Playgroud)\n

如果您发现自己在这里并且尚未阅读它,请查看 Miguel Grinberg 的这篇关于实现软删除模式随附存储库的优秀博客文章

\n

\xc2\xa0

\n

  • 尽管我非常感谢 Miguel Grinberg 在教程方面的工作和他的建议,但我认为博客文章并不是一个很好的例子。它有点旧,而且也很老套。我相信在 2021 年,正确的方法是在 SQLAlchemy 文档中描述的,并且与 SQLAlchemy 2.0 兼容 https://docs.sqlalchemy.org/en/14/_modules/examples/extending_query/filter_public.html比 Miguel 在他的博客中展示的要干净得多,并且也是 SQLAlchemy 开发人员推荐的。 (4认同)