重写flask_sqlalchemy的BaseQuery下面的filter_by方法

前言

  • 引出重写的原因,我们是通过软删除的方式来删除数据的(即通过status标识来确定数据是否作废)
  • 那么这样的话,我们每一次查询的时候都要写上条件status=1很繁琐。我们可以重写filter_by方法

源码介绍

如上图所示我们现在使用的查询方式并不是SQLAlchemy原生的查询方式,而是flask_sqlalchemy(是对原生SQLAlchemy的一个封装),是因为flask觉得原生的SQLAlchemy不是很方便,就以原生的为基础自己封装了一个flask_sqlalchemy实现了它自己的一些更加方便的查询。所以说上面的query对象是flask_sqlalchemy下面的一个对象。

  • 下面我们flask_sqlalchemy查看源码

  • 在__init__文件的407行有一个BaseQuery

  • 可以看出是继承了orm.Query,这个就是原生SQLAlchemy包里面的一个对象。我们可以看到在BaseQuery下面是没有实现filter_by方法的。下面我们在看一下orm.Query的源码

  • 而在这个文件的1559行就找到了filter_by

  • 可以看到他接收一组参数**kwargs,这个参数就是我们下图传入进来的键值对。kwargs是一个字典!!!

  • 然后在filter_by内部进行了下图源码的处理(我们这里不用管)

  • 如果说我们只需要自己实现filter_by,然后在filter_by的内部加上status=1,最后在调用基类的filter_by方法,就可以完成我们的覆盖改写。

代码编写

  • 下面开始敲代码啦:
  • 首先导入flask_sqlalchemy的BaseQuery

  • 上图只是仅仅实现我们自己的逻辑了。我们还需要完成filter_by原有的逻辑。

  • 调用基类下面的filter_by方法:上图只是仅仅实现我们自己的逻辑了。我们还需要完成filter_by原有的逻辑。

  • 在传入字典的时候我们必须要对字典进行解包所以要传入两个*号

  • 可以看到基类里面是有return的,所以我们要是不return就会有问题,我们需要return一下

  • 现在我们就完成了自定义的Query,但是还没有替换原来的BaseQuery,就要去看一下源码。flask_sqlalchemy给了我们一个替换他原有BaseQuery的机会。这个机会就在flask_sqlalchemy这个他实例化的地方。下面我们在看一次源码:

  • 可以看到在她的构造函数里面是允许传入一个自己的BaseQuery的

  • 这样我们就用自己定义的Query替代了flask_sqlalchemy的BaseQuery

  • 上图就完成了重写flask_sqlalchemy的filter_by方法

  • 所以当我们再调用query对象下面的filter_by方法的时候,就不是调用原来BaseQuery下面的filter_by了,而是调用我们自己改写的这个filter_by。

  • 在替换完成之后我们所有的filter_by中都不需要传入status=1了。

附上代码

class Query(BaseQuery):
    def filter_by(self, **kwargs):
        if 'status' not in kwargs.keys():
            kwargs['status'] = 1
        return super(Query, self).filter_by(**kwargs)
    
    # 以下方法是重写了BaseQuery类下面的方法,目的是抛出我们自定义的异常
    def get_or_404(self, ident, description=None):
        """返回指定主键对应的行,如不存在,抛出自定义异常类"""

        rv = self.get(ident)
        if rv is None:
            raise ValError(msg='未查询到该数据')
        return rv

    def first_or_404(self, description=None):
        """返回查询的第一个结果,如果未查到,抛出自定义异常类"""

        rv = self.first()
        if rv is None:
            raise ValError(msg='未查询到该数据')
        return rv


db = SQLAlchemy(query_class=Query)
原文地址:https://www.cnblogs.com/se7enjean/p/12848656.html