为不正确的标题Flask引发自定义异常

时间:2018-03-23 08:16:52

标签: python python-3.x flask

我正在构建一个没有前端的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 标题。

1 个答案:

答案 0 :(得分:1)

我通过为每个错误状态代码创建自定义错误处理程序来解决此问题。我意识到当我使用{'Content-Type':'application/x-www-form-urlencoded'}时, mimetype request.form.get()标头是必需的。这是因为表单中的信息在发送到服务器时会被编码。我现在使用了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)

现在,当我在POST请求中发送json数据或无效数据时,我收到json个例外。由于我已经更正了我的代码以回应所需的结果,因此不再有Programmingerrors

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