jsonify Flas中的SQLAlchemy结果集

2024-04-28 16:42:13 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在尝试用Flask/Python对SQLAlchemy结果集进行jsonify。

烧瓶邮件列表建议使用以下方法http://librelist.com/browser//flask/2011/2/16/jsonify-sqlalchemy-pagination-collection-result/#04a0754b63387f87e59dda564bde426e

return jsonify(json_list = qryresult)

但是我得到了以下错误:

TypeError: <flaskext.sqlalchemy.BaseQuery object at 0x102c2df90> 
is not JSON serializable

我在这里俯瞰什么?

我发现了这样一个问题:How to serialize SqlAlchemy result to JSON?看起来非常相似,但是我不知道Flask是否有一些魔法可以像邮件列表所建议的那样让它变得更容易。

编辑:为了澄清,这就是我的模特

class Rating(db.Model):

    __tablename__ = 'rating'

    id = db.Column(db.Integer, primary_key=True)
    fullurl = db.Column(db.String())
    url = db.Column(db.String())
    comments = db.Column(db.Text)
    overall = db.Column(db.Integer)
    shipping = db.Column(db.Integer)
    cost = db.Column(db.Integer)
    honesty = db.Column(db.Integer)
    communication = db.Column(db.Integer)
    name = db.Column(db.String())
    ipaddr = db.Column(db.String())
    date = db.Column(db.String())

    def __init__(self, fullurl, url, comments, overall, shipping, cost, honesty, communication, name, ipaddr, date):
        self.fullurl = fullurl
        self.url = url
        self.comments = comments
        self.overall = overall
        self.shipping = shipping
        self.cost = cost
        self.honesty = honesty
        self.communication = communication
        self.name = name
        self.ipaddr = ipaddr
        self.date = date

Tags: nameselfurldbstringcolumnintegercomments
3条回答

以下是通常对我来说足够的:

我创建了一个用于模型的序列化mixin。序列化函数基本上获取SQLAlchemy检查器公开的任何属性并将其放入dict中

from sqlalchemy.inspection import inspect

class Serializer(object):

    def serialize(self):
        return {c: getattr(self, c) for c in inspect(self).attrs.keys()}

    @staticmethod
    def serialize_list(l):
        return [m.serialize() for m in l]

现在需要做的就是用Serializermixin类扩展SQLAlchemy模型。

如果有不希望公开的字段或需要特殊格式的字段,只需重写模型子类中的serialize()函数。

class User(db.Model, Serializer):
    id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String)
    password = db.Column(db.String)

    # ...

    def serialize(self):
        d = Serializer.serialize(self)
        del d['password']
        return d

在控制器中,您只需调用结果上的serialize()函数(如果查询结果为列表,则调用serialize_list(l)):

def get_user(id):
    user = User.query.get(id)
    return json.dumps(user.serialize())

def get_users():
    users = User.query.all()
    return json.dumps(User.serialize_list(users))

我也有同样的需要,序列化成json。看看this question。它展示了如何以编程方式发现列。所以,从那开始我创建了下面的代码。它对我有效,我将在我的网络应用程序中使用它。快乐编码!


def to_json(inst, cls):
    """
    Jsonify the sql alchemy query result.
    """
    convert = dict()
    # add your coversions for things like datetime's 
    # and what-not that aren't serializable.
    d = dict()
    for c in cls.__table__.columns:
        v = getattr(inst, c.name)
        if c.type in convert.keys() and v is not None:
            try:
                d[c.name] = convert[c.type](v)
            except:
                d[c.name] = "Error:  Failed to covert using ", str(convert[c.type])
        elif v is None:
            d[c.name] = str()
        else:
            d[c.name] = v
    return json.dumps(d)

class Person(base):
    __tablename__ = 'person'
    id = Column(Integer, Sequence('person_id_seq'), primary_key=True)
    first_name = Column(Text)
    last_name = Column(Text)
    email = Column(Text)

    @property
    def json(self):
        return to_json(self, self.__class__)

似乎你还没有执行你的查询。尝试以下操作:

return jsonify(json_list = qryresult.all())

[编辑]:jsonify的问题是,通常无法自动对对象进行jsonify。即使Python的datetime失败;)

我过去所做的是向需要序列化的类添加一个额外的属性(比如serialize)。

def dump_datetime(value):
    """Deserialize datetime object into string form for JSON processing."""
    if value is None:
        return None
    return [value.strftime("%Y-%m-%d"), value.strftime("%H:%M:%S")]

class Foo(db.Model):
    # ... SQLAlchemy defs here..
    def __init__(self, ...):
       # self.foo = ...
       pass

    @property
    def serialize(self):
       """Return object data in easily serializable format"""
       return {
           'id'         : self.id,
           'modified_at': dump_datetime(self.modified_at),
           # This is an example how to deal with Many2Many relations
           'many2many'  : self.serialize_many2many
       }
    @property
    def serialize_many2many(self):
       """
       Return object's relations in easily serializable format.
       NB! Calls many2many's serialize property.
       """
       return [ item.serialize for item in self.many2many]

现在我可以做的是:

return jsonify(json_list=[i.serialize for i in qryresult.all()])

希望这有帮助;)

[编辑2019]: 如果有更复杂的对象或循环引用,请使用类似marshmallow的库。

相关问题 更多 >