Невозможно опубликовать в flask restful конечную точку с Python

У меня есть конечная точка, которая принимает JSON

api.add_resource(EventsList, '/events')

Алхимия Flask 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, я получаю сообщение об ошибке сервера.

Питон

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 -

Любая помощь приветствуется.


person TheMightyLlama    schedule 28.09.2020    source источник


Ответы (2)


Исправлено.

Проблема заключалась в том, как я отправлял данные на сервер. Вот что у меня было:

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 = {'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)
person TheMightyLlama    schedule 29.09.2020

У вас есть данные 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'
person Gord Thompson    schedule 28.09.2020
comment
Проблема, по-видимому, связана с запросом, полученным конечной точкой и проанализированным в ресурсе, а не с ответом, полученным клиентом, как вы предлагаете. - person TheMightyLlama; 28.09.2020
comment
Вы написали код в api.py? Трассировка стека показывает, что ошибка возникает в строке 155 этого файла. - person Gord Thompson; 28.09.2020
comment
Да, строка 155: title = request.json['title'] в POST выше. - person TheMightyLlama; 28.09.2020
comment
Таким образом, вам нужно запустить строку request.json через json.loads, прежде чем пытаться извлечь ['title']. - person Gord Thompson; 29.09.2020