Python Flask Sqlalchemy模型通过调用模型返回不同的结果。uu dict_uuu(有时显示backrefs,有时显示don';t)

Python Flask Sqlalchemy模型通过调用模型返回不同的结果。uu dict_uuu(有时显示backrefs,有时显示don';t),python,json,flask,sqlalchemy,flask-sqlalchemy,Python,Json,Flask,Sqlalchemy,Flask Sqlalchemy,我想从查询中获得结果并将其与jsonify一起发送给客户端,我创建了一个函数来获取模型的实例,使用其“dict”属性删除未使用的值,如“\sa\u instance\u state”,然后将新字典作为jsonified对象返回给客户端。 这是我的密码: def display(Object): data= Object.__dict__.copy() del data['_sa_instance_state'] return data` user

我想从查询中获得结果并将其与
jsonify
一起发送给客户端,我创建了一个函数来获取模型的实例,使用其“dict”属性删除未使用的值,如
“\sa\u instance\u 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序列化

管理员在哪里 另一个
模型
,在用户模型中有backref。 奇怪的事情发生在这里,因为有时候不做任何改变,我就不会出错。
当我试图找出jupyter笔记本中发生的事情时,我发现
\uu dict\uuu
jupyter笔记本中不显示backrefs,但有时在我从flask应用程序调用它时,它会显示backrefs。

不要在SQLAlchemy模型上使用
\uu dict\uu
。是的,可能存在反向引用,其他SQLAlchemy特定信息也可能存在

你可以用它来弄到那个。然后,您可以决定在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
    }
上面使用跳过任何相关对象。处理相关对象的另一种方法是递归地将它们转换为字典:

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()
方法,或者在该模型上使用一个Flask附加组件,就更容易了。

不要在SQLAlchemy模型上使用
\u dict\uu
。是的,可能存在反向引用,其他SQLAlchemy特定信息也可能存在

你可以用它来弄到那个。然后,您可以决定在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
    }
上面使用跳过任何相关对象。处理相关对象的另一种方法是递归地将它们转换为字典:

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()
方法添加到生成字典以反映的模型中,或者使用Flask附加组件,就更容易了