mal*_*wan 112 python sqlalchemy flask flask-sqlalchemy
我正在尝试在Flask/Python中jsonify一个SQLAlchemy结果集.
Flask邮件列表建议采用以下方法:http://librelist.com/browser//flask/2011/2/16/jsonify-sqlalchemy-pagination-collection-result/#04a0754b63387f87e59dda564bde426e:
return jsonify(json_list = qryresult)
Run Code Online (Sandbox Code Playgroud)
但是我收到以下错误:
TypeError: <flaskext.sqlalchemy.BaseQuery object at 0x102c2df90>
is not JSON serializable
Run Code Online (Sandbox Code Playgroud)
我在这里俯瞰什么?
我发现了这个问题:如何将SqlAlchemy结果序列化为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
Run Code Online (Sandbox Code Playgroud)
pla*_*aes 155
看来你实际上还没有执行你的查询.试试以下:
return jsonify(json_list = qryresult.all())
Run Code Online (Sandbox Code Playgroud)
[编辑]:jsonify问题是,通常对象不能自动进行jsonified.甚至Python的日期时间都失败了;)
我通常做的是为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]
Run Code Online (Sandbox Code Playgroud)
现在我可以做的观点:
return jsonify(json_list=[i.serialize for i in qryresult.all()])
Run Code Online (Sandbox Code Playgroud)
希望这可以帮助 ;)
bit*_*cle 36
我有同样的需要,序列化为json.看看这个问题.它显示了如何以编程方式发现列.所以,从那以后我创建了下面的代码.它适用于我,我将在我的网络应用程序中使用它.快乐的编码!
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__)
Run Code Online (Sandbox Code Playgroud)
Car*_*rot 34
这通常对我来说足够了:
我创建了一个序列化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]
Run Code Online (Sandbox Code Playgroud)
现在所需要的只是使用Serializer
mixin类扩展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
Run Code Online (Sandbox Code Playgroud)
在您的控制器中,您所要做的就是在结果上调用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))
Run Code Online (Sandbox Code Playgroud)
n0n*_*ker 18
这是我的方法:https: //github.com/n0nSmoker/SQLAlchemy-serializer
pip安装SQLAlchemy-serializer
您可以轻松地将mixin添加到模型中,而不仅仅是在它的实例上调用.to_dict()方法
您也可以在SerializerMixin的基础上编写自己的mixin
对于平面查询(无联接),您可以执行此操作
@app.route('/results/')
def results():
data = Table.query.all()
result = [d.__dict__ for d in data]
return jsonify(result=result)
Run Code Online (Sandbox Code Playgroud)
如果您只想从数据库中返回某些列,则可以执行此操作
@app.route('/results/')
def results():
cols = ['id', 'url', 'shipping']
data = Table.query.all()
result = [{col: getattr(d, col) for col in cols} for d in data]
return jsonify(result=result)
Run Code Online (Sandbox Code Playgroud)
好的,我已经研究了几个小时,并且已经开发出了我认为是迄今为止最pythonic的解决方案。以下代码段是python3,但如果需要的话,应该不要太费劲地向后移植。
我们要做的第一件事是从一个mixin开始,它使您的数据库模型有点像dict
s:
from sqlalchemy.inspection import inspect
class ModelMixin:
"""Provide dict-like interface to db.Model subclasses."""
def __getitem__(self, key):
"""Expose object attributes like dict values."""
return getattr(self, key)
def keys(self):
"""Identify what db columns we have."""
return inspect(self).attrs.keys()
Run Code Online (Sandbox Code Playgroud)
现在,我们将继承mixin来定义我们的模型:
class MyModel(db.Model, ModelMixin):
id = db.Column(db.Integer, primary_key=True)
foo = db.Column(...)
bar = db.Column(...)
# etc ...
Run Code Online (Sandbox Code Playgroud)
这一切都需要能够通过一个实例MyModel()
来dict()
,并得到一个活生生的dict
例子了吧,这会让我们致力于使相当长的路jsonify()
了解它。接下来,我们需要扩展JSONEncoder
以获取其余的方法:
from flask.json import JSONEncoder
from contextlib import suppress
class MyJSONEncoder(JSONEncoder):
def default(self, obj):
# Optional: convert datetime objects to ISO format
with suppress(AttributeError):
return obj.isoformat()
return dict(obj)
app.json_encoder = MyJSONEncoder
Run Code Online (Sandbox Code Playgroud)
优点:如果模型包含计算字段(也就是说,您希望JSON输出包含实际上未存储在数据库中的字段),那么这也很容易。只需将您的计算字段定义为@property
s,然后keys()
像这样扩展方法:
class MyModel(db.Model, ModelMixin):
id = db.Column(db.Integer, primary_key=True)
foo = db.Column(...)
bar = db.Column(...)
@property
def computed_field(self):
return 'this value did not come from the db'
def keys(self):
return super().keys() + ['computed_field']
Run Code Online (Sandbox Code Playgroud)
现在对jsonify进行琐碎的工作:
@app.route('/whatever', methods=['GET'])
def whatever():
return jsonify(dict(results=MyModel.query.all()))
Run Code Online (Sandbox Code Playgroud)
如果您正在使用,flask-restful
可以使用marshal:
from flask.ext.restful import Resource, fields, marshal
topic_fields = {
'title': fields.String,
'content': fields.String,
'uri': fields.Url('topic'),
'creator': fields.String,
'created': fields.DateTime(dt_format='rfc822')
}
class TopicListApi(Resource):
def get(self):
return {'topics': [marshal(topic, topic_fields) for topic in DbTopic.query.all()]}
Run Code Online (Sandbox Code Playgroud)
您需要明确列出您要返回的内容以及它的类型,对于 api 来说我更喜欢这样。序列化很容易处理(不需要jsonify
),日期也不是问题。请注意,该字段的内容uri
是根据topic
端点和 ID 自动生成的。
归档时间: |
|
查看次数: |
106472 次 |
最近记录: |