无法 post 使用 Python 烧瓶 restful 端点

Unable to post to flask restful endpoint with Python

我有一个端点接受 JSON

api.add_resource(EventsList, '/events')

合剂 Restful / SQL 炼金术是:

class EventsList (Resource):
    #RETURNS ALL EVENTS
    def get(self):
        schema = EventSchema()
        result = db.session.query(EventModel).all()
        return schema.dump(result, many=True), 200

    #POSTS A SINGLE EVENT
    def post(self):

        title = request.json['title']
        date = request.json['date']

        event = EventModel(title=title,date=date)

        db.session.add(event)
        db.session.commit()

        data = ({'title': event.title,
                 'date': event.date})

        response = jsonify(data)
        response.status_code = 200
        return response

当通过命令行使用 curl 时,这绝对没问题:

卷曲请求

curl http://localhost:5002/events -H "Content-Type: application/json" -d '{"title": "TEst Event 3", "date":"2020-02-23"}'

卷曲响应

响应包含预期的数据:

{"date":"Sun, 23 Feb 2020 00:00:00 GMT","title":"TEst Event 3"}

一切正常。但是,当我尝试从 Python 执行此操作时,我收到服务器错误。

Python

import importlib
import subprocess
import csv
import sys
import requests

targetWikiPage = input("Target Wiki Page: ")
eventTitle = input("Event Title: ")
eventDate = input("Event Date: ")

    
#POST AN EVENT
data = '{"title": "'+eventTitle+'","date":"'+eventDate+'"}'
print("SENDING EVENT DATA:")
print(requests.body)
print(requests.headers)

response = requests.post("http://localhost:5002/events", json=data)

服务器控制台输出

[2020-09-28 16:38:14,182] ERROR in app: Exception on /events [POST]
Traceback (most recent call last):
  File "/usr/local/lib/python3.8/site-packages/flask/app.py", line 1950, in full_dispatch_request
    rv = self.dispatch_request()
  File "/usr/local/lib/python3.8/site-packages/flask/app.py", line 1936, in dispatch_request
    return self.view_functions[rule.endpoint](**req.view_args)
  File "/usr/local/lib/python3.8/site-packages/flask_restful/__init__.py", line 468, in wrapper
    resp = resource(*args, **kwargs)
  File "/usr/local/lib/python3.8/site-packages/flask/views.py", line 89, in view
    return self.dispatch_request(*args, **kwargs)
  File "/usr/local/lib/python3.8/site-packages/flask_restful/__init__.py", line 583, in dispatch_request
    resp = meth(*args, **kwargs)
  File "api.py", line 155, in post
    title = request.json['title']
TypeError: string indices must be integers
127.0.0.1 - - [28/Sep/2020 16:38:14] "POST /events HTTP/1.1" 500 -

感谢任何帮助。

您在字符串对象中有 JSON 数据。尝试通过字符串的键从字符串中提取值将产生您描述的错误

>>> response = '{"date":"Sun, 23 Feb 2020 00:00:00 GMT","title":"TEst Event 3"}'
>>> response_date = response["date"]
Traceback (most recent call last):
  File "<pyshell#1>", line 1, in <module>
    response_date = response["date"]
TypeError: string indices must be integers

您需要先将字符串转换为dict,然后提取值

>>> import json
>>> response_as_json = json.loads(response)
>>> response_date = response_as_json["date"]
>>> response_date
'Sun, 23 Feb 2020 00:00:00 GMT'

已修复此问题。

问题在于我如何将数据发送到服务器。这是我的:

targetWikiPage = input("Target Wiki Page: ")
eventTitle = input("Event Title: ")
eventDate = input("Event Date: ")

    
#POST AN EVENT
data = '{"title": "'+eventTitle+'","date":"'+eventDate+'"}'
print("SENDING EVENT DATA:")
print(requests.body)
print(requests.headers)

response = requests.post("http://localhost:5002/events", json=data)

请注意,我的 requests.post 传递了两个值。 url 和数据。

问题如下:

  1. 数据格式不正确。这应该是:

data = json.dumps({"title": eventTitle, "date": eventDate})

  1. 我需要添加 headers:

headers = {'Content-type': 'application/json', 'Accept': 'text/plain'}

  1. 我需要向服务器传递一个 data 值,而不是 json

requests.post("http://localhost:5002/events", headers=headers, data=data)

将我的文件更改为:

targetWikiPage = input("Target Wiki Page: ")
eventTitle = input("Event Title: ")
eventDate = input("Event Date: ")

#POST AN EVENT
data = json.dumps({"title": eventTitle, "date": eventDate})
headers = {'Content-type': 'application/json', 'Accept': 'text/plain'}
print(data)
print(headers)
print("SENDING EVENT DATA:")

response = requests.post("http://localhost:5002/events", headers=headers, data=data)
json=json.loads(response.content)