Python Flask SQLalchemy JSON POST 错误

Posted

技术标签:

【中文标题】Python Flask SQLalchemy JSON POST 错误【英文标题】:Python Flask SQLalchemy JSON POST Error 【发布时间】:2015-02-20 22:28:17 【问题描述】:

我正在尝试发布以下 JSON 并保存到 Flask 服务器和 Python 2.7、restless 框架和带有 curl 的 SQLAlchemy 上的 mysql 数据库:

curl -i -H "Accept: application/json" -X POST  -d '"attribute_id": "1", "product_id": "44","text":"Something","language":"1"' http://seroney-pc:5000/api/attributes


    "attribute_id": "1",
    "product_id": "44",
    "text": "Something",
    "language": "1"

我的代码如下:

from flask import Flask,request,jsonify, abort
from flask_sqlalchemy import SQLAlchemy
import flask_restless


app = Flask(__name__)
db = SQLAlchemy(app)
manager = flask_restless.APIManager(app)

app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql://root:seroney@localhost:3306/test'


class Attributes(db.Model):
    __tablename__ = 'oc_product_attribute'
    product_id = db.Column(db.Integer,primary_key=True)
    attribute_id = db.Column(db.Integer,primary_key=True)
    language_id = db.Column(db.Integer,primary_key=True)
    text=db.Column(db.String)

@app.route('/api/attributes/',methods=['GET'])
def getProductAttributes():
    if request.method =='GET':
        results = Attributes.query.limit(10).offset(0).all()
        json_results = []
        for result in results:
            d = 
                'product_id':result.product_id,
                'attribute_id':result.attribute_id,
                'language_id':result.language_id,
                'text':result.text
            
            json_results.append(d)

        return jsonify(items = json_results)

@app.route('/api/attributes/', methods=['POST'])

def postProductAttributes():
    product_id = request.json['product_id']
    attribute_id = request.json['attribute_id']
    language_id = request.json['language_id']
    text = request.json['text']
    if product_id is None or attribute_id is None or language_id is None or text is None:
        return jsonify("message": "Error."), 400
    new_attrib = (product_id,attribute_id,language_id,text)
    db.session.add(new_attrib)
    db.session.commit()
    return jsonify('message' :'Attribute Created successfully'), 200

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

当我发布时,我不断收到内部服务器错误。非常感谢任何帮助。

回溯是:

seroney-pc - - [23/Dec/2014 20:48:40] "POST /api/attributes HTTP/1.1" 500 -
Traceback (most recent call last):
  File "/usr/local/lib/python2.7/dist-packages/flask/app.py", line 1836, in __call__
    return self.wsgi_app(environ, start_response)
  File "/usr/local/lib/python2.7/dist-packages/flask/app.py", line 1820, in wsgi_app
    response = self.make_response(self.handle_exception(e))
  File "/usr/local/lib/python2.7/dist-packages/flask/app.py", line 1403, in handle_exception
    reraise(exc_type, exc_value, tb)
  File "/usr/local/lib/python2.7/dist-packages/flask/app.py", line 1817, in wsgi_app
    response = self.full_dispatch_request()
  File "/usr/local/lib/python2.7/dist-packages/flask/app.py", line 1477, in full_dispatch_request
    rv = self.handle_user_exception(e)
  File "/usr/local/lib/python2.7/dist-packages/flask/app.py", line 1381, in handle_user_exception
    reraise(exc_type, exc_value, tb)
  File "/usr/local/lib/python2.7/dist-packages/flask/app.py", line 1475, in full_dispatch_request
    rv = self.dispatch_request()
  File "/usr/local/lib/python2.7/dist-packages/flask/app.py", line 1453, in dispatch_request
    self.raise_routing_exception(req)
  File "/usr/local/lib/python2.7/dist-packages/flask/app.py", line 1439, in raise_routing_exception
    raise FormDataRoutingRedirect(request)

注意:此异常仅在调试模式下引发

【问题讨论】:

记录了 500 内部服务器错误。你的控制台说什么?应该有追溯,请在您的帖子中包含。 您如何发布 JSON 数据?您是否在上面使用了 application/json 的 Content-Type 标头? @MartijnPieters,我已经用 traceback info 和 curl post 命令更新了这个问题。谢谢你。非常感谢任何帮助 这是整个回溯吗?异常消息可能仍然包含更多信息,并且缩进到与Traceback 相同的级别(例如,根本没有缩进)。 异常文档字符串为: 如果请求方法不是GET、HEAD或OPTIONS时检测到路由系统引起的重定向,则Flask在调试模式下会引发此异常。推理:表单数据将被丢弃。 【参考方案1】:

您将发布到 URL 没有末尾的 /,但您指定了您的路线 尾随 /。当您这样做时,Flask 会使用 / 发出重定向到“规范”URL。

因为您使用的是 POST,所以帖子数据会丢失,因此在调试模式下会引发异常,通知您应该在帖子中使用尾部斜杠。

如果您查看了错误消息的正文,您会看到如下内容:

FormDataRoutingRedirect: 请求已发送到此 URL (http://seroney-pc:5000/api/attributes) 但重定向是 由路由系统自动发送到“http://seroney-pc:5000/api/attributes/”。 URL 是用斜杠定义的,因此如果在没有斜杠的情况下访问该 URL,Flask 将自动重定向到带有斜杠的 URL。请确保将您的 POST 请求直接发送到此 URL,因为我们无法使浏览器或 HTTP 客户端使用表单数据可靠地重定向或无需用户交互。

注意:此异常仅在调试模式下引发

Rule Format documentation:

以斜杠结尾的 URL 规则是分支 URL,其他的是叶子。如果您启用了 strict_slashes(这是默认设置),所有访问的不带斜杠的分支 URL 都会触发重定向到附加了斜杠的相同 URL。

请注意,您的curl POST 使用了错误的标题;您需要设置 Content-Type 标头。您的视图正在寻找 language_id 键,但您的帖子仅包含 language 键,您也需要更正:

curl -i -H "Content-Type: application/json" -X POST \
     -d '"attribute_id": "1", "product_id": "44","text":"Something","language_id":"1"' http://seroney-pc:5000/api/attributes/

Accept 标头也可能有用,但它用于协商响应内容类型,并且您将视图硬编码为返回 JSON。

您创建数据库对象的代码也不正确,您需要调用模型并将参数作为单独的参数传递,然后将结果传递给session.add()

new_attrib = Attributes(*new_attrib)
db.session.add(new_attrib)

但在这里重用 JSON 对象会更容易:

db.session.add(Attributes(**request.json))

【讨论】:

我已经附加了尾随 / 但我得到了一个新的回溯 Traceback (最近一次调用最后一次): raise ValueError('View function did not return a response') ValueError: View function didn't return回应 @Seroney:你确定你发帖的路线正确吗?当我使用更正后的 POST 测试您的代码时,我得到一个不同的错误(因为您没有设置正确的 Content-Type 标头)。 @Seroney:通过额外的修复,我可以让你的代码正常工作。 我有一个快速的问题,我如何验证 request.json 例如,如果 Attributes.query.filter_by(**request.json).first 不是 None:本质上是我想要实现的是一个产品不应该有多个attribute_id 我正在使用sqlalchemy,我是新手。 :-) 验证应该是产品不应该能够创建相同的属性,需要针对db进行验证

以上是关于Python Flask SQLalchemy JSON POST 错误的主要内容,如果未能解决你的问题,请参考以下文章

python flask orm sqlalchemy 实例

python web开发-flask中使用sqlalchemy

python web开发-flask中sqlalchemy的使用

python-flask-Flask-SQLAlchemy与Flask-Migrate联合进行数据化迁移

python flask_Sqlalchemy管理数据库

Python Flask SQLAlchemy 分页