美文网首页
直接通过 jsonify()处理sqlalchemy orm返回

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

作者: royluck | 来源:发表于2021-06-23 11:29 被阅读0次

    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方法。

    • app.py

    !!! 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
    

    相关文章

      网友评论

          本文标题:直接通过 jsonify()处理sqlalchemy orm返回

          本文链接:https://www.haomeiwen.com/subject/qzbpyltx.html