简单 Flask python 后端中 POST 方法的 KeyError

KeyError on POST method in simple Flask python backend

我正在尝试使用 MongoDB 和 python(pycharm) 中的 Flask 创建一个简单的 API 和服务器。我正在使用 Postman 测试这些方法,到目前为止 GET 和 DELETE 方法有效。我主要在使用 POST 方法时遇到麻烦(用于添加实体)。我有 2 classes

存储库class

class ExercisesRepository:

    def __init__(self):
        self.client = MongoClient('localhost', 27017)
        self.client.drop_database("exercise_database")  # clear everything that was before
        self.db = self.client.exercise_database  # create database
        self.exercises = self.db.exercises  # create table in the database

    def get_all(self):
        return [{
            'id': str(exercise['_id']),
            'type': exercise['type'],
            'calories': exercise['calories']
        } for exercise in self.exercises.find()]

    def add(self, exercise):
        exercise = {key: exercise[key] for key in exercise}
        exercise['calories'] = int(exercise['calories'])  #line 24
        self.exercises.insert_one(exercise)  # automatically generates an ObjectId for the exercise
        return 200

    def update(self, exercise_id, exercise):
        my_query = {"_id": ObjectId(exercise_id)}
        new_values = {"$set": {"type": exercise["type"], "calories": exercise["calories"]}}
        self.exercises.update_one(my_query, new_values)
        return 200

    def delete(self, exercise_id):
        self.exercises.remove(ObjectId(exercise_id))
        return 200

    def check_database_content(self):
        for exercise in self.exercises.find():
            pprint.pprint(exercise)

服务器class

from ExercisesRepository import ExercisesRepository

from flask import Flask
from flask import request
from flask import jsonify
import sys


app = Flask(__name__)

exerciseRepo = ExercisesRepository()

exerciseRepo.add({'type': 'Yoga', 'calories': 500})
exerciseRepo.add({'type': 'Walk', 'calories': 300})
exerciseRepo.add({'type': 'Run', 'calories': 100})


@app.route('/')
def hello_world():
    return 'Hello World!'


@app.route("/exercises", methods=['GET', 'POST'])
def exercises():
    if request.method == 'GET':
        return jsonify(exerciseRepo.get_all())
    elif request.method == 'POST':
        print(request.form, file=sys.stderr)
        return jsonify(exerciseRepo.add(request.form))  #line 31


@app.route('/exercises/<exercise_id>', methods=['PUT', 'DELETE'])
def exercises_id(exercise_id):
    if request.method == 'PUT':
        print(request.form, file=sys.stderr)
        return jsonify(exerciseRepo.update(exercise_id, request.form))
    elif request.method == 'DELETE':
        return jsonify(exerciseRepo.delete(exercise_id))


if __name__ == '__main__':
    app.run()

当我尝试用这样的 JSON 在邮递员中进行 POST 调用时: { "type": "Aerobic", "calories": 500 我在邮递员中收到以下消息:500 Internal Server Error 内部服务器错误 服务器遇到内部错误,无法完成您的请求。服务器过载或应用程序中存在错误。 在 Pycharm 控制台中:

File "server.py", line 31, in exercises return jsonify(exerciseRepo.add(request.form))
server\ExercisesRepository.py", line 24, in add exercise['calories'] = int(exercise['calories']) KeyError: 'calories' 127.0.0.1 - - [05/Jan/2020 13:01:50] "POST /exercises HTTP/1.1" 500 -

我是 python 的新手,这是我第一次尝试制作 api,所以如果您能尽可能多地解释一下,那将非常有帮助。谢谢!

如果您将数据作为 JSON 发送,那么您必须使用 request.json 获取它,而不是 request.form

from flask import Flask, request, jsonify

app = Flask(__name__)

@app.route("/exercises", methods=['GET', 'POST'])
def exercises():
    print('form:', request.form)
    print('json:', request.json)
    return jsonify(request.json)  #line 31

if __name__ == '__main__':
    app.run()

当您发送为 JSON

import requests

r = requests.post('http://localhost:5000/exercises', json={'type': 'Run', 'calories': 100})

然后服务器显示

form: ImmutableMultiDict([])
json: {'type': 'Run', 'calories': 100}

当您发送 form 数据时

import requests

r = requests.post('http://localhost:5000/exercises', data={'type': 'Run', 'calories': 100})

然后服务器显示

form: ImmutableMultiDict([('type', 'Run'), ('calories', '100')])
json: None

form 在正文中将数据作为字符串 type=Run&calories=100 发送,
json 在正文中将数据作为字符串 {'type': 'Run', 'calories': 100} 发送。

显示请求正文就可以看到

import requests

r = requests.post('https://httpbin.org/post', data={'type': 'Run', 'calories': 100})
print(r.request.body)

r = requests.post('https://httpbin.org/post', json={'type': 'Run', 'calories': 100})
print(r.request.body)

结果

type=Run&calories=100
b'{"type": "Run", "calories": 100}'