使用flask restful的自定义错误消息json对象

使用flask restful的自定义错误消息json对象,flask,werkzeug,flask-restful,Flask,Werkzeug,Flask Restful,使用flask restful,使用abort()方法可以很容易地将错误消息传播到客户端,例如 abort(500, message="Fatal error: Pizza the Hutt was found dead earlier today in the back seat of his stretched limo. Evidently, the notorious gangster became locked in his car and ate himself to death."

使用flask restful,使用
abort()
方法可以很容易地将错误消息传播到客户端,例如

abort(500, message="Fatal error: Pizza the Hutt was found dead earlier today
in the back seat of his stretched limo. Evidently, the notorious gangster
became locked in his car and ate himself to death.")
这将生成以下json输出

{
  "message": "Fatal error: Pizza the Hutt was found dead earlier today
       in the back seat of his stretched limo. Evidently, the notorious gangster
       became locked in his car and ate himself to death.", 
  "status": 500
}
有没有办法使用其他成员自定义json输出?例如:

{
  "sub_code": 42,
  "action": "redirect:#/Outer/Space"
  "message": "You idiots! These are not them! You've captured their stunt doubles!", 
  "status": 500
}

人们倾向于过度使用
abort()
,而事实上,生成自己的错误非常简单。您可以轻松编写生成自定义错误的函数,下面是一个与JSON匹配的函数:

def make_error(status_code, sub_code, message, action):
    response = jsonify({
        'status': status_code,
        'sub_code': sub_code,
        'message': message,
        'action': action
    })
    response.status_code = status_code
    return response
然后,不要调用
abort()
执行以下操作:

@route('/')
def my_view_function():
    # ...
    if need_to_return_error:
        return make_error(500, 42, 'You idiots!...', 'redirect...')
    # ...

显然已经晚了,但与此同时,正如作者所指出的,RESTful设法提供了一种更干净的方法来处理错误


此外,我还公开表示改进可能会有所帮助。

我没有50%的声誉来评论@dappiu,所以我只需要写一个新的答案,但它确实与“Flask RESTful设法提供一种更干净的方法来处理错误”有关

这是一个如此糟糕的文档,我花了一段时间才弄明白如何使用它。关键是自定义异常必须从restful import HTTPException继承。请注意,您不能使用Python异常

from flask_restful import HTTPException

class UserAlreadyExistsError(HTTPException):
    pass

custom_errors = {
    'UserAlreadyExistsError': {
        'message': "A user with that username already exists.",
        'status': 409,
    }
}

api = Api(app, errors=custom_errors)

Flask RESTful团队在简化自定义异常处理方面做得很好,但文档破坏了这项工作。

我必须为我的子类
HttpException
定义属性

from werkzeug.exceptions import HTTPException
from flask_restful import Api
from flask import Blueprint

api_bp = Blueprint('api',__name__)

class ResourceAlreadyExists(HTTPException):
    code = 400

errors = {
    'ResourceAlreadyExists': {
        'message': "This resource already exists.",
        'status': 409,
    },
}

api = Api(api_bp, errors=errors)
然后,稍后,提出异常

raise ResourceAlreadyExists

正如@Miguel所示,通常不应该使用异常,只需返回一些错误响应。然而,有时您确实需要一个引发异常的中止机制。例如,这在过滤方法中可能很有用。请注意,接受一个对象(选中此项):


我不同意@Miguel关于
abort()
的相关性的观点。除非您使用Flask构建HTTP应用程序以外的其他应用程序(使用请求/响应范例),否则我认为您应该尽可能多地使用
HTTPExceptions
(请参阅
werkzeug.exceptions
模块)。它还意味着使用中止机制(这只是这些异常的快捷方式)。相反,如果您选择显式构建并在视图中返回自己的错误,则会导致您进入一种模式,需要使用一系列If/else/return来检查值,这通常是不必要的。请记住,您的函数很可能在请求/响应管道的上下文中运行。在做出决定之前,不必一路返回视图,只需在失败点中止请求并完成即可。该框架完全理解这种模式,并且具有其偶然性。如果需要,您仍然可以捕获异常(可能是为了补充额外的消息,或者是为了挽救请求)

因此,与@Miguel类似,但保持了预期的流产机制:

 def json_abort(status_code, data=None):
    response = jsonify(data or {'error': 'There was an error'})
    response.status_code = status_code
    abort(response)

# then in app during a request

def check_unique_username(username):
    if UserModel.by__username(username):
        json_abort(409, {'error': 'The username is taken'})

def fetch_user(user_id): 
    try:
        return UserModel.get(user_id)
    except UserModel.NotFound:
        json_abort(404, {'error': 'User not found'})
使用烧瓶静置(0.3.8或更高)

诀窍是使用

因此,例如,如果您想要处理400请求,您应该向customErrors json对象添加BadRequest

或者,如果您想处理404错误,那么在json对象中使用NotFound
等等

实际上,文档没有明确(至少对我来说)如何定义自定义错误消息。没有代码使用它的例子。@FrancisDavey将带有自定义错误的dict传递给Api构造函数,如文档中的示例,然后在需要时“引发MyCustomError”,并让flask restful完成其余的操作。flask restful所做的是为您在errors dict.Thank中指定的每个异常设置一个@app.errorhandler(MyCustomError)。不清楚的是,字典中的名称是您在其他地方通过子类化Exception创建的异常的名称。至少我认为它应该这样做。正如我所说,没有使用它的示例代码,所以很难说。仔细阅读那一页仍然让我有点困惑。因此我问了这个问题。@dappiu-我得到了
namererror:全局名称“InvalidEmailError”没有定义
。我在包的init.py文件中定义了我的错误,我正试图在紧邻init.py的views.py文件中
引发InvalidEmailError
-知道我为什么会得到
NameError
?我同意Francis的观点——文档中的示例非常简洁,现在还不清楚这些键是字符串还是真的应该是例外,我无法让它工作。非常感谢实际运行的示例代码。您不需要从HTTPException进行扩展。使用Exception可以很好地工作,您只需记住将debug设置为FALSE即可查看正确的错误响应,否则它将进入debug并显示html stacktrace错误。Yes。更明确地说:
class useralreadyexisterror(Exception)
不从flask\u restful导入HTTPException就足够了这将不允许您发送自定义错误消息,是吗?(我的意思是在发生异常时。)正如@Sebastian所说的那样-必须禁用Flask调试模式(
false
)。我能知道如何从参考资料代码中引发
UseralReadyExistError
吗?我同意这很好,也很干净,但有时确实需要中止机制(有异常)避免到处写if+return。这太简单了,在嵌套函数中毫无用处。
 def json_abort(status_code, data=None):
    response = jsonify(data or {'error': 'There was an error'})
    response.status_code = status_code
    abort(response)

# then in app during a request

def check_unique_username(username):
    if UserModel.by__username(username):
        json_abort(409, {'error': 'The username is taken'})

def fetch_user(user_id): 
    try:
        return UserModel.get(user_id)
    except UserModel.NotFound:
        json_abort(404, {'error': 'User not found'})
from flask_restful import Api
customErrors = {
    'NotFound': {
        'message': "The resource that you are trying to access does not exist",
        'status': 404,
        'anotherMessage': 'Another message here'
    },
    'BadRequest': {
        'message': "The server was not able to handle this request",
        'status': 400,
        'anotherMessage': 'Another message here'
    }
}
app = Flask(__name__)
api = Api(app, catch_all_404s=True, errors=customErrors)