gpt4 book ai didi

python - FLASK REST API 在 POST 上返回 400

转载 作者:行者123 更新时间:2023-12-01 06:45:31 26 4
gpt4 key购买 nike

我正在使用 Flask 和 SQLAlchemy 作为 ORM 为简单的 Todo 应用程序构建 REST API。我正在使用 Postman 测试我的 API。我使用的是 Windows 10 64 位计算机。

GET 请求起作用并返回我使用 python 输入到数据库中的数据。

Get Request

我现在想尝试添加任务。但是当我发布请求时,我收到错误。

POST request

我在 flask 中的路线如下所示。

#add task
@app.route('/todo/api/v1.0/tasks', methods=['POST'])
def create_task():
if not request.json or not 'title' in request.json:
raise InvalidUsage('Not a valid task!', status_code=400)
task = {
'title': request.json['title'],
'description': request.json['description'],
'done': False
}
Todo.add_todo(task)
return jsonify({'task': task}), 201

它在 Todo 对象上调用的方法如下所示。

def add_todo(_title, _description):
new_todo = Todo(title=_title, description=_description , completed = 0)
db.session.add(new_todo)
db.session.commit()

我尝试过的

我认为也许我的 Postman Params 中的 ' 引起了问题,所以我删除了它们。但我仍然遇到同样的错误。

然后我认为 Postman 发送 POST 的方式可能不正确,因此我检查以确保 Content-Type header 正确。它设置为 application/json

最后,为了确认问题是 Flask 不喜欢该请求,我删除了添加任务路由中的检查以确保该请求有标题。所以它看起来像这样。

if not request.json:

我也遇到同样的错误。所以我认为问题一定是我实际发送 POST 的方式而不是某种格式问题。

我的整个代码如下所示。

from flask import Flask
from flask_sqlalchemy import SQLAlchemy
import json
from flask import jsonify
from flask import request

app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///todo.db'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
db = SQLAlchemy(app)

class Todo(db.Model):
id = db.Column(db.Integer, primary_key=True)
title = db.Column(db.String(300), unique=False, nullable=False)
description = db.Column(db.String(), unique=False, nullable=False)
completed = db.Column(db.Boolean, nullable=False)

def json(self):
return {'id': self.id,'title': self.title, 'description': self.description, 'completed': self.completed}

def add_todo(_title, _description):
new_todo = Todo(title=_title, description=_description , completed = 0)
db.session.add(new_todo)
db.session.commit()

def get_all_tasks():
return [Todo.json(todo) for todo in Todo.query.all()]

def get_task(_id):
task = Todo.query.filter_by(id=_id).first()
if task is not None:
return Todo.json(task)
else:
raise InvalidUsage('No task found', status_code=400)

def __repr__(self):
return f"Todo('{self.title}')"




class InvalidUsage(Exception):
status_code = 400

def __init__(self, message, status_code=None, payload=None):
Exception.__init__(self)
self.message = message
if status_code is not None:
self.status_code = status_code
self.payload = payload

def to_dict(self):
rv = dict(self.payload or ())
rv['message'] = self.message
return rv

@app.route('/')
def hello_world():
return 'Hello to the World of Flask!'

#get all tasks
@app.route('/todo/api/v1.0/tasks', methods=['GET'])
def get_tasks():
return_value = Todo.get_all_tasks()
return jsonify({'tasks': return_value})

#get specific task
@app.route('/todo/api/v1.0/tasks/<int:task_id>', methods=['GET'])
def get_task(task_id):
task = Todo.get_task(task_id)
#if len(task) == 0:
#raise InvalidUsage('No such task', status_code=404)
return jsonify({'task': task})

#add task
@app.route('/todo/api/v1.0/tasks', methods=['POST'])
def create_task():
if not request.json or not 'title' in request.json:
raise InvalidUsage('Not a valid task!', status_code=400)
task = {
'title': request.json['title'],
'description': request.json['description'],
'done': False
}
Todo.add_todo(task)
return jsonify({'task': task}), 201

#update task
@app.route('/todo/api/v1.0/tasks/<int:task_id>', methods=['PUT'])
def update_task(task_id):
task = [task for task in tasks if task['id'] == task_id]
if len(task) == 0:
raise InvalidUsage('No provided updated', status_code=400)
if not request.json:
raise InvalidUsage('request not valid json', status_code=400)
if 'title' in request.json and type(request.json['title']) != unicode:
raise InvalidUsage('title not unicode', status_code=400)
if 'description' in request.json and type(request.json['description']) != unicode:
raise InvalidUsage('description not unicode', status_code=400)
if 'done' in request.json and type(request.json['done']) is not bool:
raise InvalidUsage('done not boolean', status_code=400)
task[0]['title'] = request.json.get('title', task[0]['title'])
task[0]['description'] = request.json.get('description', task[0]['description'])
task[0]['done'] = request.json.get('done', task[0]['done'])
return jsonify({'task': task[0]})

#delete task
@app.route('/todo/api/v1.0/tasks/<int:task_id>', methods=['DELETE'])
def delete_task(task_id):
task = [task for task in tasks if task['id'] == task_id]
if len(task) == 0:
raise InvalidUsage('No task to delete', status_code=400)
tasks.remove(task[0])
return jsonify({'result': True})


@app.errorhandler(InvalidUsage)
def handle_invalid_usage(error):
response = jsonify(error.to_dict())
response.status_code = error.status_code
return response

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

编辑:

事实证明我没有正确设置 POSTMAN 中的请求类型。我已将其更新为 header 中的“application/json”。现在我收到一个不同的错误。

Bad Request Failed to decode JSON object: Expecting value: line 1 column 1 (char 0)

我已经像以前一样尝试了前面的所有步骤,但我仍然收到此错误。

Badrequest

编辑2:

根据下面的回复,我尝试将这些值放入 POST 正文中。但我仍然收到 400 回复。

body

最佳答案

从图像[第二个 postman 屏幕截图]来看,您似乎在查询字符串中传递数据,但create_task()期望它们在请求正文中.

create_task() 中将所有出现的 request.json 替换为 request.args (以使其与查询参数一起使用)或保持原样并在请求正文中发送数据。

curl -X POST http://localhost:5000/todo/api/v1.0/tasks \
-H "Content-Type: application/json" \
-d '{"title":"Learn more flask","description":"its supper fun"}'

此外,请查看 Get the data received in a Flask request .


已编辑

将您的 add_todo 更新为类似的内容

@classmethod
def add_todo(cls, task):
new_todo = cls(title=task["title"], description=task["description"], completed=0)
db.session.add(new_todo)
db.session.commit()

相关:generalised insert into sqlalchemy using dictionary .

关于python - FLASK REST API 在 POST 上返回 400,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59238781/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com