python - Flask Sqlalchemy 模型通过调用 model.__dict__ 返回不同的结果(有时显示反向引用,有时不显示)
问题描述
我想从查询中获取结果并将其发送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 可序列化的
其中 admin 是另一个model
在 User 模型中有一个 backref 的地方。这里发生了奇怪的事情,因为有时没有改变任何东西我没有得到错误。当我试图找出 jupyter 笔记本中发生的事情时,我发现__dict__
它没有显示 backrefs,jupyter notebook
但有时当我从烧瓶应用程序调用它时它会显示 backrefs。
解决方案
不要__dict__
在 SQLAlchemy 模型上使用。是的,可能存在反向引用,具体取决于您配置引用加载的方式,其他 SQLAlchemy 特定信息也是如此。
您可以使用运行时自省来获取InstanceState
实例。然后,您可以决定在 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
命名空间跳过任何相关对象。处理相关对象的另一种方法是递归地将它们转换为字典:
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()
就个人而言,我发现向我的模型添加一个方法来生成要反射的字典,或者使用提供反射 API的 Flask 插件更容易。
推荐阅读
- google-cloud-platform - Bigquery - 安排存储过程不再工作
- javascript - 如何在 JavaScript 中用点减去数字?
- javascript - 获取另一个角色时如何删除角色(discord.js)
- python - Matlotlib:如何将 subplot-number 传递给 floating_axes.FloatingSubplot 方法?
- java - 更新 ArrayList 适配器
- azure - 如何在 azure 中从虚拟机 ping 负载均衡器 IP 地址
- python - 如何使用 python 库 pyjq 将字符串转换为 int?
- php - 避免专门针对特定产品的 WooCommerce 新订单通知
- python - (django) 根据用户的兴趣显示帖子
- php - symfony - 在 form->handleRequest 处注销