【问题标题】:Flask: Converting Python dict to json object for client apiFlask:将 Python dict 转换为客户端 api 的 json 对象
【发布时间】:2014-06-18 16:10:10
【问题描述】:

我需要从烧瓶中创建一个 json 对象作为查询结果。然后我需要将 json 对象传递给路由以创建 API。

在寻找一些巧妙的方法来从我的实例创建字典时,我偶然发现了这个 post 中的一个方法,它可以使用实例的内部字典并将 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 路由时,我得到一个只有“id”字段的 json 对象:

rests: [
{
id: 28450
},
{
id: 28795
},
{
id: 30439
},
{
id: 29325
},
{
id: 29765
},
{
id: 29928
},
{
id: 30383
},
{
id: 29064
},
{
id: 29862
},
{
id: 28610
}
]
}

我已经转了几个小时,不知道为什么视图行为会与 python API 不同。也许这是我对 jsonify 做错了,但我不这么认为。

【问题讨论】:

  • 您已经导入的“dumps({...})”有什么问题?
  • @swstephe dumps 给了我同样的错误——只显示“id”字段

标签: python json dictionary flask


【解决方案1】:

您对模型进行 jsonifying 的方法通常是个坏主意:

  • 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)

根据您的应用程序,您可以通过将字段(尤其是日期时间字段)转换为 javascript 友好格式或添加方便的字段(如遵循关系)来使 as_dict 更智能。

【讨论】:

  • @paolocasiello 有没有办法直接传递一个 dict 对象在模板中使用?如果是这样,这是否有益?
  • 你是说 Jinja 模板?您可以将整个模型传递给模板render_template(..., mod=model),并直接从模板中使用函数/属性
  • 非常感谢!这对我帮助很大!
猜你喜欢
  • 2018-01-08
  • 1970-01-01
  • 1970-01-01
  • 2019-11-27
  • 2017-04-27
  • 2019-10-08
  • 1970-01-01
  • 1970-01-01
  • 2016-09-23
相关资源
最近更新 更多