【问题标题】:Raise custom exception for incorrect header Flask为不正确的标头 Flask 引发自定义异常
【发布时间】:2018-03-23 08:16:51
【问题描述】:

我正在构建一个还没有前端的 Flask REST API。我已经成功地为 Flask 视图开发了一个 GET 请求,该视图从 SQL 数据库中获取所有订阅者。我通过对数据库的 POST 请求对 INSERT VALUES 使用相同的 Flask 视图。为了清理输入,我使用(%s) 作为值的占位符。以下是代码的摘录:

#main.py
@app.route('/api/subscribe/', methods=['GET', 'POST'])
def subscribe():
    if request.method == 'GET':
        try:
            data = DB.get_subscription_list()
            return Response(json.dumps({'result': data}, cls=DateTimeEncoder, sort_keys=True), mimetype='application/json')
        except Exception as e:
            return e
    elif request.method == 'POST':
        try:
            email = request.form.get('email')
            data = DB.add_email(email)
            return Response(json.dumps({'result': 'Email added to database'}, cls=DateTimeEncoder, sort_keys=True), mimetype='application/json')
        except Exception as e:
            return e


#dbhelper.py
def add_email(self,data):
    connection = self.connect()
    try:
        #The following adds an email entry to the 'users' table.
        query = "INSERT INTO users (email) VALUES (%s);"
        with connection.cursor() as cursor:
            cursor.execute(query,data)
            connection.commit()
    except pymysql.ProgrammingError as e:
        print(e)
        raise e   
    finally:
        connection.close()

我已经用更准确的信息和针对我的问题的具体信息编辑了这个问题。

我目前正在 RESTClient 和 Postman 上测试 API。

当我发送带有标头{'Content-Type':'application/x-www-form-urlencoded'} 的POST 请求时,值插入成功。输出:{"result": "Email added to database"}。如果不使用此标头,我会在下面收到 Programmingerror 异常:

(1064, "You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '%s)' at line 1")

如何为不正确的标头条目引发自定义异常,以便引发此自定义异常而不是显示语法错误?当然,这不是语法错误,因为使用 时成功插入了值urlencoded 标头。

【问题讨论】:

  • 您正在打印异常而不是引发异常!在 print(e) 下面添加 raise e
  • 是的,现在至少返回错误。这不是编程错误,而是与标头参数有关。 Flask 无法识别标头错误?我想分别提出一个编程错误异常和一个标头异常。

标签: python python-3.x flask


【解决方案1】:

我通过为每个错误状态代码创建自定义错误处理程序解决了这个问题。我意识到当我使用request.form.get() 时需要mimetype {'Content-Type':'application/x-www-form-urlencoded'} 标头。这是因为表单中的信息在发送到服务器时会进行编码。我现在使用了request.json.get(),因为我想在json 中发送数据,现在需要的标头是{'Content-Type':'application/json'} mimetype。所以,现在我的观点是这样的:

#subscribe.py
@app.route('/api/users/subscribe', methods=["GET", "POST"])
def subscribe():
    if request.method == "GET":
        try:
            data = DB.get_subscription_list()
            return Response(json.dumps({'result': data}, cls=DateTimeEncoder, sort_keys=True), mimetype='application/json', status=200)
        except Exception:
            return Response(json.dumps({'error': 'Could not fetch subscribers from database.'}), status=500)
    elif request.method == "POST":
        try:
            email = request.json.get("email")
            data = DB.add_email(email)
            return Response(json.dumps({'result': 'Email added to database.'}, cls=DateTimeEncoder, sort_keys=True), mimetype='application/json', status=201)
        except Exception:
            return Response(json.dumps({'error': 'Could not add to database.'}), status=500)

注意,上面每个方法的自定义错误异常。我还创建了自定义错误处理程序,以防出现带有状态代码的错误并且我没有为它们明确定义异常。例如,如果在html 中呈现状态代码500 的错误,则下面的错误处理程序将在json 中显示自定义错误。我为状态码 405、401 等添加了类似的错误处理程序,因此我总是在json 中收到自定义错误。

@app.errorhandler(500)
def method_not_allowed(error):
    return make_response(jsonify({'error': 'An error occurred during a request'}), 500)

同样,我为数据库查询添加了一个例外:

#dbhelper.py
try:
    #The following adds an email entry to the 'users' table.
    uri = url_for('subscribe', email=email, _external=True)
    query = "INSERT INTO users (email) VALUES (%s);"
    with connection.cursor() as cursor:
        cursor.execute(query,email)
        connection.commit()
except Exception:  
    return Response(json.dumps({'error':'Database connection error.'}), status=500)

现在,当我不以 json 格式发送数据或在我的 POST 请求中发送无效数据时,我收到了 json 异常。没有Programmingerrors 了,因为我已经更正了我的代码以响应所需的结果。

更有条理的方法是在单独的errors.py 文件中定义自定义错误类,并在必要时调用异常函数。

【讨论】:

    猜你喜欢
    • 2018-08-14
    • 1970-01-01
    • 1970-01-01
    • 2013-01-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多