我想从查询中获取结果并将其与jsonify
发送给客户端,我创建了一个获取模型实例的函数,使用其' dict '属性删除未使用的值,例如'_sa_instance_state'
,然后将新字典作为jsonified对象返回给客户端。
这是我的代码:
def display(Object):
data= Object.__dict__.copy()
del data['_sa_instance_state']
return data`
user = User.query.first()
@app.route('/')
def main():
return jsonify(display(user))
有时我会收到此错误
TypeError:Admin类型的对象不可JSON序列化
管理员在哪里
另一个model
在用户模型中具有反向引用。
奇怪的事情在这里发生,因为有时不做任何更改我不会得到错误。
当我尝试找出Jupyter笔记本中发生的情况时,我发现__dict__
在jupyter notebook
中没有显示反向引用,但是有时当我从flask应用程序调用它时,它会显示反向引用。>
答案 0 :(得分:2)
请勿在SQLAlchemy模型上使用__dict__
。是的,可能存在反向引用 depending on how you configured reference loading,其他SQLAlchemy特定信息也可能存在。
您可以使用runtime introspection来获取InstanceState
instance。然后,您可以决定要在JSON中反映什么以及应该忽略什么:
from operator import attrgetter
from sqlalchemy import inspect
def display(object, only_loaded=False):
insp = inspect(object)
assert insp.is_instance
value = attrgetter('loaded_value' if only_loaded else 'value')
return {
name: value(attr) for name, attr in insp.attrs.items()
if name not in insp.mapper.relationships
}
以上内容使用Mapper.relationships
namespace来跳过任何相关对象。处理相关对象的另一种方法是将它们也递归地转换成字典:
def display(object, include_related=True, only_loaded=False, seen=None):
insp = inspect(object)
assert insp.is_instance
value = attrgetter('loaded_value' if only_loaded else 'value')
result = {
name: value(attr) for name, attr in insp.attrs.items()
if name not in insp.mapper.relationships
}
if include_related:
if seen is None:
seen = set()
seen.add(id(object))
for name, rel in insp.mapper.relationships.items():
related = value(insp.attrs[name])
if related is not None:
if rel.uselist:
displays = result[name] = []
for r in related:
if id(r) in seen:
continue
displays.append(display(r, True, only_loaded, seen))
else:
if id(related) in seen:
continue
result[name] = display(related, True, only_loaded)
return result
但是要考虑到,使用双向关系对象,您可能很快就会反映出比您预期的要大得多的数据库块。
就个人而言,我发现将as_dict()
方法添加到产生字典以反映或使用provides a reflection API的Flask附加组件的模型中比较容易。