Flask: 将Python字典转换为JSON对象供客户端API使用
我需要从Flask的查询结果创建一个json对象,然后把这个json对象传递给路由,以便创建一个API。
在寻找一些简单的方法来从我的实例创建字典时,我发现了一个帖子,里面提到可以使用实例的内部字典,并在模型类中添加一个叫做'jsond'的方法。下面是带有这个自定义方法'jsond'的模型:
from app import db
class Rest(db.Model):
id = db.Column(db.Integer, primary_key = True)
name = db.Column(db.String(100), unique = True)
street = db.Column(db.Text)
zipcd = db.Column(db.Integer)
comments = db.relationship('Comment', backref='rest', lazy='dynamic')
lat = db.Column(db.Float(6))
lng = db.Column(db.Float(6))
def __init__(self,name,street,zipcd):
self.name = name
self.street = street
self.zipcd = zipcd
def __repr__(self):
return '{}'.format(self.name)
def name_slug(self):
return self.name
def jsond(self):
instDict = self.__dict__.copy()
if instDict.has_key('_sa_instance_state'):
del instDict['_sa_instance_state']
return instDict
这是我的视图函数:
from app import app, db
from flask import render_template, flash, redirect, session, url_for, request, g, jsonify, make_response
from flask.json import dumps
from flask.ext import restful
from flask.ext.httpauth import HTTPBasicAuth
from models import Comment, Rest, Badge
from helper import make_badges, make_inspections, loc_query
import operator
auth = HTTPBasicAuth()
@app.route('/api',methods=['GET'])
def makeApi():
###Query Parameters###
lim = request.args.get('limit', 10)
off = request.args.get('offset', 0)
loc = request.args.get('location', "39.94106,-75.173192")
lat, lng = loc.split(",")
radius = request.args.get('radius',2)
query = loc_query(lat,lng,radius,off,lim)
results = Rest.query.from_statement(query).all()
rest_json = []
for rest in results:
rest_json.append(rest.jsond())
return make_response(jsonify({'count':len(rest_json),'rests':rest_json}))
所以当我在Python的API命令行中运行查询时,可以成功创建一个包含所有字段的字典(使用自定义的jsond方法)。但是当我通过我的视图访问makeApi路由时,得到的json对象只有'id'字段:
rests: [
{
id: 28450
},
{
id: 28795
},
{
id: 30439
},
{
id: 29325
},
{
id: 29765
},
{
id: 29928
},
{
id: 30383
},
{
id: 29064
},
{
id: 29862
},
{
id: 28610
}
]
}
我已经转了好几个圈,几个小时过去了,还是不知道为什么视图的行为和Python API会不一样。也许是我在使用jsonify时做错了什么,但我觉得不是。
1 个回答
4
一般来说,把模型转成 JSON 的方法并不好:
self.__dict__
里面可能会有很多没有文档说明的键- 列的类型:你不能直接把
relationship
和列的类型转成 JSON,特别是datetime
类型的列。 - 安全性:有时候你可能想隐藏一些字段(比如对不可信的用户使用你的 API 时)。
一个好的做法是创建一个方法,返回一个可以转成 JSON 的字典:
class Foo(db.Model):
field1 = db.Column(...)
field2 = db.Column(...)
def as_dict(self):
obj_d = {
'field1': self.field1,
'field2': self.field2,
...
}
return obj_d
然后在你的视图中:
foos = Foo.query.all()
results = [ foo.as_dict() for foo in foos ]
return jsonify({count: len(results), results: results)
根据你的应用,你可以让 as_dict
更聪明一点,把字段(特别是日期时间字段)转换成 JavaScript 更友好的格式,或者添加一些方便的字段,比如跟随某个关系。