Flask-Restful 错误:请求内容类型不是“application/json”。”}

问题描述 投票:0回答:8

我正在关注这个教程并且进展顺利。然后他介绍了

reqparse
,我也跟着介绍。我尝试测试我的代码,但收到此错误
{'message': "Did not attempt to load JSON data because the request Content-Type was not 'application/json'."}

我不知道我是否遗漏了一些非常明显的东西,但我很确定我准确地复制了他的代码。这是代码:

main.py

from flask import Flask, request
from flask_restful import Api, Resource, reqparse

app = Flask(__name__)
api = Api(app)

#basic get and post
names = {"sai": {"age": 19, "gender": "male"},
            "bill": {"age": 23, "gender": "male"}}
class HelloWorld(Resource):
    def get(self, name, numb):
        return names[name]

    def post(self):
        return {"data": "Posted"}

api.add_resource(HelloWorld, "/helloworld/<string:name>/<int:numb>")

# getting larger data
pictures = {}
class picture(Resource):
    def get(self, picture_id):
        return pictures[picture_id]

    def put(self, picture_id):
        print(request.form['likes'])
        pass

api.add_resource(picture, "/picture/<int:picture_id>")

# reqparse
video_put_args = reqparse.RequestParser() # make new request parser object to make sure it fits the correct guidelines
video_put_args.add_argument("name", type=str, help="Name of the video")
video_put_args.add_argument("views", type=int, help="Views on the video")
video_put_args.add_argument("likes", type=int, help="Likes on the video")

videos = {}

class Video(Resource):
    def get(self, video_id):
        return videos[video_id]

    def post(self, video_id):
        args = video_put_args.parse_args()
        print(request.form['likes'])
        return {video_id: args}

api.add_resource(Video, "/video/<int:video_id>")

if __name__ == "__main__":
    app.run(debug=True)

test_rest.py

import requests

BASE = "http://127.0.0.1:5000/"

response = requests.post(BASE + 'video/1', {"likes": 10})

print(response.json())
python rest flask flask-restful
8个回答
4
投票

如果您能够更改代码

我设法通过将

location=<target>
添加到
parser.add_argument()
函数来解决这个问题。

  parser.add_argument("email", type=str, required=True)
+ parser.add_argument("email", type=str, required=True, location='form')

您需要添加输入数据的正确位置。一些可能的值为

json
args
form
。了解更多信息: https://flask-restful.readthedocs.io/en/latest/api.html#reqparse.RequestParser.parse_args

就我而言,是

form
。因为我使用
multipart/form-data
作为输入。

如果您无法更改代码

werkzeug
降级到此提交之前的版本

信用:Flask-restx 请求解析器返回 400 错误请求


3
投票

据我所知,我不知道为什么你有问题,你确实复制了他的做法。这是一个可行的修复程序,尽管我无法解释为什么他的代码有效而你的代码无效。他的视频已有两年历史,因此可能已被弃用。

import requests
import json

BASE = "http://127.0.0.1:5000/"

payload = {"likes": 10}

headers = {'accept': 'application/json'}
response = requests.post(BASE + 'video/1', json=payload)

print(response.json())

3
投票

当前正在遵循相同的教程并面临相同的问题。 通过为数据添加关键字参数

json
解决了我的问题

response = requests.post(BASE + 'video/1', json={"likes": 10})

1
投票

您可以按照错误消息所述设置标题。

import requests, json

BASE = "http://127.0.0.1:5000/"
# Set request's header.
headers = {"Content-Type": "application/json; charset=utf-8"}
# Set data.
data = {"likes": 10}
# 
response = requests.post(BASE + 'video/1', headers=headers, json=data)

print("Status Code: ", response.status_code)
print("JSON Response: ", response.json())

1
投票

您可以使用

Response.get_json()
方法而不是
json
属性,它允许您指定
force
参数:

force
(bool) — 忽略 mimetype 并始终尝试解析 JSON

用法将是:

import requests

response = requests.post('http://127.0.0.1:5000/video/1', {'likes': 10})

response_data_forced_json = response.get_json(force=True)

这实际上是获取

Response.json
属性时所调用的,仅使用默认参数。


1
投票

azzamsa 是正确的。我可以添加以下内容:如果您的 API 工作正常,但在模块更新后突然停止,并出现类似于

Did not attempt to load JSON data because the request Content-Type was not 'application/json'
的错误,也许您正在使用带参数的
GET
,例如对我来说
curl "http://localhost:5000/api/mac?mac=3c:52:82:17:2e:e8"
。我的代码是

parser = reqparse.RequestParser()
parser.add_argument("mac", type=str)
args = parser.parse_args()

更改为后

parser = reqparse.RequestParser()
parser.add_argument("mac", type=str ,location='args')
args = parser.parse_args()

我得到了以前的行为,并且可以在修复后阅读

args['mac']


0
投票

我也遇到过类似的麻烦。我有关于内容类型的错误,但是在 Flask-restx 中。 我的结论是使用 reqparse 来定义所需的参数,并且也用于获取此参数,否则您会得到相同的错误。

我使用 reqparse 来定义 file_uploader 和 api.payload 来获取其他数据

upload_parser = api.parser()
upload_parser.add_argument('file', location='files',
                           type=FileStorage, required=True)

hostauth_create_fields = api.model(
    'HostAuthCreate', {
        'name': fields.String(description="The name of the instance", required=True),
        'username': fields.String(description="Username to connect", required=True),
        'password': fields.String(description="Password to connect", required=False)
    }
)

@api.route('/api/hostauth')
class HostAuthView(Resource):
    @api.expect(upload_parser, hostauth_create_fields)
    def post(self):
        args = upload_parser.parse_args()
        args.get('file')
        api.payload.get('name') # This line will cause a error
        return {'name': args.get('name')}, 201

但是可以通过 upload_parser 解析所有参数:

upload_parser = api.parser()
upload_parser.add_argument('file', location='files',
                           type=FileStorage, required=True)
upload_parser.add_argument('name', type=str, required=True, location="form")
upload_parser.add_argument('username', type=str, required=True, location="form")
upload_parser.add_argument('password', type=str, location="form")

要获取其他参数,请使用:

args.get('name')

可能 api.model 重写了负责 reqparse 设置的接受内容类型的标头。因此,如果您有文件作为参数,您应该选择 reqparse。在其他路线中你可以再次使用 api.model


0
投票

pip install -r 要求.txt

文件requirements.txt,例如:

  • Flask==1.1.2 Flask-Cors==3.0.8
  • Flask-RESTful==0.3.8
  • Jinja2==2.11.2
  • 标记安全==1.1.1
  • 其危险==1.1.0
  • Werkzeug==1.0.1

-> 我认为这个错误是 Flask 版本 > 2.0 造成的。 如果您使用 Flask 版本 > 2.0,则添加 location ='form':

例如:parse.add_argument('ID', location='form')

© www.soinside.com 2019 - 2024. All rights reserved.