第五章:flask-SQLAlchemy的自定制

1.使flask-SQLAlchemy对象自动支持commit()

from flask_sqlalchemy import SQLAlchemy as _SQLAlchemy
from contextlib import contextmanager

class SQLAlchemy(_SQLAlchemy):
    @contextmanager
    def auto_commit(self):
        try:
            yield
            self.session.commit()
        except Exception as e:
            self.session.rollback()
            raise e

db = SQLAlchemy()

###### 例如 #######
from app.libs.user import User
with db.auto_commit():
    user = User()
    user.email = 'xxx'
    user.nickname = 'xxx'
    user.password = 'xxx'
    db.session.add(user)

2.自定制flask-SQLAlchemy中的BaseQuery

目标: 使fliter_by默认查询status=1

分析:BaseQuery继承自Query,filter_by在Query中,要重写filter_by方法
from flask_sqlalchemy import BaseQuery as _BaseQuery
from flask_sqlalchemy import SQLAlchemy as _SQLAlchemy
from contextlib import contextmanager

class SQLAlchemy(_SQLAlchemy):
    @contextmanager
    def auto_commit(self):
        try:
            yield
            self.session.commit()
        except Exception as e:
            self.session.rollback()
            raise e


class BaseQuery(_BaseQuery):
    def filter_by(self, **kwargs):
        if 'status' not in kwargs:   #如果status字段不在fliter_by中,默认添加status=1
            kwargs['status'] = 1
        return super(BaseQuery, self).filter_by(**kwargs) #返回父类的fliter_by的执行


db = SQLAlchemy(query_class=BaseQuery)  # 在SQLAlchemy中注册一下

        ### 查询 ###
user_List = User.query.filter_by(xxx=xxx,xxx=xxx) # 默认status=1, 方便查询被逻辑删除的数据

3.自定制BaseQuery下的first_or_404

BaseQuery源码

class BaseQuery(orm.Query):
    """SQLAlchemy :class:`~sqlalchemy.orm.query.Query` subclass with convenience methods for querying in a web application.

    This is the default :attr:`~Model.query` object used for models, and exposed as :attr:`~SQLAlchemy.Query`.
    Override the query class for an individual model by subclassing this and setting :attr:`~Model.query_class`.
    """
    ...
    ...

    def first_or_404(self):
        """Like :meth:`first` but aborts with 404 if not found instead of returning ``None``."""

        rv = self.first()
        if rv is None:
            abort(404)
        return rv

由此可见它出错会抛出404的(HTML)异常,我们重写它抛出json的异常结果

class BaseQuery(_BaseQuery):
    ...
    ...

    def first_or_404(self):   # 重写
        rv = self.first()
        if rv is None:
            raise My_not_found()   # 此处改写
        return rv

### 查询后就不必判断对象是否为空
user = User.query.filter_by(xxx=xxx,xxx=xxx).first_or_404()

猜你喜欢

转载自blog.csdn.net/lilied001/article/details/80803143