【问题标题】:How to parse the POST argument to a REST service?如何将 POST 参数解析为 REST 服务?
【发布时间】:2013-10-23 10:51:30
【问题描述】:

看来我还有另一个 JSON 问题,这次是在发布到 REST 服务时。 我正在使用Flask-Restful

api.add_resource(Records, '/rest/records/<string:email>/<string:password>/<string:last_sync_date>')

parser = reqparse.RequestParser()
parser.add_argument('record_date', type=str)
parser.add_argument('records', type=str)
parser.add_argument('rating', type=str)
parser.add_argument('notes', type=str)

class Records(Resource):
    def post(self, email, password, last_sync_date):
        args = parser.parse_args()
        records = args['records'] # 'records' = None, but why? 
        return records, 201

单元测试:

resource_fields = {
            'record_date': fields.String,
            'rating': fields.Integer,
            'notes': fields.String,
            'last_updated': fields.DateTime,
        }
records = {"records":[]}
records["records"].append(marshal(record1, resource_fields))
    rv = self.app.post('/rest/records/{0}/{1}/{2}'.format(email, password, sync_date), data=json.dumps(records))

json.dumps(records) 是:

str: {"records": [{"rating": 1, "notes": null, "last_updated": "Tue, 15 Oct 2013 15:52:44 -0000", "record_date": "2013-10-15 15:52:44.746815"}]}

为什么args['records'] 没有,我显然是通过网络发送的?

更新:

奇怪的是,当我发送一个对象时,它全是花花公子。好奇怪:

record = dict(record_date=record1.record_date, rating=record1.rating, notes=record1.notes, last_updated=record1.last_updated)

rv = self.app.post('/rest/records/{0}/{1}/{2}'.format(email, password, sync_date), data=record)

参数

{'records': None, 'notes': None, 'task': None, 'record_date': '2013-10-15 16:48:40.662744', 'rating': '1'}

【问题讨论】:

  • parser 是如何定义的?同样在def post 内部,args 是什么,即在records = args['records'] 之后的行,log.debug(args)print(args)
  • parser = reqparse.RequestParser()print(args) = Namespace: {'records': None, 'notes': None, 'task': None, 'record_date': None, 'rating': None}
  • from flask import requestprint(request.form) 是否包含不同的数据?或者,来自the docs,也许您需要查看的是request.values
  • request.formImmutableMultiDict: ImmutableMultiDict([])request.valuesCombinedMultiDict: CombinedMultiDict([ImmutableMultiDict([]), ImmutableMultiDict([])])
  • 看起来数据由于某种原因实际上并未发布。完全没有。您可能会考虑使用 wireshark 或 fiddle 来查看数据是否真的从机器中取出 - 或尝试使用 httpbin.org

标签: python json rest flask flask-restful


【解决方案1】:

我最终在flask-resful github上提出了这个问题,并得到了这个对我有用的解决方案。归功于 Doug Black。

reqparse 并不真正知道如何处理 JSON。要处理 JSON 帖子,您需要使用 flask.request.json 字典。

这是您可能想要的更新示例:

from flask import Flask, request
from flask.ext import restful

class Records(restful.Resource):
    def post(self, email, password, last_sync_date):
        records = request.json['records']
        return records, 201

app = Flask(__name__)
api = restful.Api(app)
api.add_resource(
    Records, 
    '/rest/records/<string:email>/<string:password>/<string:last_sync_date>'
)

request.json 上的文档在这里。

您需要确保在发布时将内容类型标头设置为 application/json,以便烧瓶知道填充 json 字典。

self.app.post(
    '/rest/records/{0}/{1}/{2}'.format(email, password, sync_date), 
    data=json.dumps(records), 
    headers={'Content-Type': 'application/json'
)

【讨论】:

  • 是的,这行得通,令人不快的是您需要检查 json dict 是否不是None
【解决方案2】:
class Records(Resource):
    parser = reqparse.RequestParser()
    parser.add_argument('record_date', type=str)
    parser.add_argument('records', type=str)
    parser.add_argument('rating', type=str)
    parser.add_argument('notes', type=str)

    def post(self):
        args = parser.parse_args()
        records = args['records']
        return records, 201

我希望它有效。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-10-13
    • 2017-10-29
    • 2023-04-08
    • 1970-01-01
    • 2015-10-30
    • 1970-01-01
    • 2012-12-31
    • 1970-01-01
    相关资源
    最近更新 更多