直接通过 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方法。
- 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