直接通过 jsonify()处理sqlalchemy orm返回

2021-06-23  本文已影响0人  royluck

python 对象转字典及序列化对象相关问题,dict!!!!必看,多坑

image.png
@api.route('/<int:uid>', methods=['GET'])
@auth.login_required
def super_get_user(uid):
  user = User.query.filter_by(id=uid).first_or_404()
  return jsonify(user)

上述直接转jsonify会报错:TypeError: Object of type User is not JSON serializable

为了直接可以直接通过 jsonify()处理sqlalchemy orm返回的数据库原始对象,所以需要在这里改造jsonify(),改造后的jsonify() 可以直接返回user实例对象对应的字典字段和属性,在重写JSONEncoder方法,我们需要使用dict()处理对象,但是默认dict是不支持处理对象的,所以我们又要在模型类继承的基础上和执行原理,去重写keys()和getitem方法。

!!! dict()方法如果传入对象 它会默认调用类的getitem和keys()方法

from flask.json import JSONEncoder as _JSONEncoder

class JSONEncoder(_JSONEncoder):
    def default(self, o):
        # 容错判断
        if hasattr(o, 'keys') and hasattr(o, '__getitem__'):
            # dict()方法如果传入对象 它会默认调用类的__getitem__和keys()方法
            return dict(o)
        if isinstance(o, date):
            return o.strftime('%Y-%m-%d')
        raise ServerError()


class Flask(_Flask):
    json_encoder = JSONEncoder


from flask_sqlalchemy import SQLAlchemy 
class Base(SQLAlchemy):
    __abstract__ = True
    create_time = Column(Integer)
    status = Column(SmallInteger, default=1)

    def __init__(self) -> object:
        self.create_time = int(datetime.now().timestamp())

    # 重写模型__getitem__方法
    # __getitem__方法会根据调用的keys()方法查询返回的key值 并获取对应key值的变量
    # 如:app/models/user.py

    def __getitem__(self, item):
        return getattr(self, item)

    @property
    def create_datetime(self):
        if self.create_time:
            return datetime.fromtimestamp(self.create_time)
        else:
            return None

    def set_attrs(self, attrs_dict):
        for key, value in attrs_dict.items():
            if hasattr(self, key) and key != 'id':
                setattr(self, key, value)

    def delete(self):
        self.status = 0

    def keys(self):
        return self.fields

    def hide(self, *keys):
        for key in keys:
            self.fields.remove(key)
        return self

    def append(self, *keys):
        for key in keys:
            self.fields.append(key)
        return self
from app.models.base import Base, db

class User(Base):
    id = Column(Integer, primary_key=True)
    email = Column(String(24), unique=True, nullable=False)
    nickname = Column(String(24), unique=True)
    # 权限等级 普通用户默认为 1
    auth = Column(SmallInteger, default=1)
    _password = Column('password', String(100))

    # 重写模型keys方法
    # dict(对象) 只能拿到对象的实例变量 拿不到类变量 需要通过上述方法该找
    # dict(o) 如果dict传入对象 其会调用对象的keys方法获取key值 然后通过中括号形式o['name']访问变量
    # 默认对象是不可以中括号的形式访问变量 o['name'] 所以要在__getitem__方法通过getattr() 方法获取对象和类的变量
    # 见app/models/user.py
    def keys(self):
        # 一个元素的元组定义需要加逗号 ('name',)
        # 使用列表就不用加逗号 ['name']
        return ['id', 'email', 'nickname', 'auth']

    @property
    def password(self):
        return self._password
上一篇下一篇

猜你喜欢

热点阅读