【问题标题】:Flask restx MarshallingError incorrect formattingFlask restx MarshallingError 格式不正确
【发布时间】:2020-06-05 11:06:55
【问题描述】:

问题背景

在使用 flask-restx 生成 api 文档时,我遇到了 MarshallingError 的一些意外行为。我有一个自定义的 flask-restx 字段定义,如下所示。

class EnumField(StringMixin, Raw):

    def __init__(self, enum_type, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.enum_type = enum_type

    def format(self, value):
        try:
            return self.enum_type(value)
        except ValueError as e:
            raise MarshallingError(e)

    def output(self, key, obj, **kwargs):
        return self.format(obj[key]).value

enum_type 很简单

class DemoEnum(Enum):
    a = 'a'
    b = 'b'
    c = 'c'

然后将其打包在一个 restx api.model 中,如下所示。

model = api.model('Demo', {"name": EnumField(enum_type=DemoEnum, required=True)})

问题

当我在name 中输入一个整数时,正如预期的那样,我得到了一个很好的错误,如下所示。

{
  "errors": {
    "name": "1 is not of type 'string'"
  },
  "message": "Input payload validation failed"
}

但是,当我在我的枚举中输入一个 not 的值(例如“d”)时,我的 format 定义中似乎发现了错误,但是 MarshallingError没有按预期隐藏所有内部错误。这是输出内容的简短 sn-p。

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
  "http://www.w3.org/TR/html4/loose.dtd">
<html>
  <head>
    <title>MarshallingError: 'string' is not a valid DemoEnum // Werkzeug Debugger</title>
...

问题

  1. 这是预期的行为吗?
  2. 是否可以返回更清晰的错误,如上图所示?我的理解是,我对format 的定义应该可以做到这一点?

完整的测试申请

from flask_restx import Api, Resource
from flask_restx.fields import Raw, StringMixin, MarshallingError

from flask import Flask
from werkzeug.middleware.proxy_fix import ProxyFix

from enum import Enum

# =============================================================================
# Custom EnumField and Enum
# =============================================================================

class EnumField(StringMixin, Raw):

    def __init__(self, enum_type, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.enum_type = enum_type

    def format(self, value):
        try:
            return self.enum_type(value)
        except ValueError as e:
            raise MarshallingError(e)

    def output(self, key, obj, **kwargs):
        return self.format(obj[key]).value

class DemoEnum(Enum):
    a = 'a'
    b = 'b'
    c = 'c'

# =============================================================================
# Demo restx model
# =============================================================================

app = Flask(__name__)
app.wsgi_app = ProxyFix(app.wsgi_app)
api = Api(app, version='1.0', title='Test API', validate=True)

ns = api.namespace('demo')

model = api.model('Demo', {
    "name": EnumField(enum_type=DemoEnum, required=True)
})

# =============================================================================
# Api endpoint
# =============================================================================

@ns.route('/')
class Demo(Resource):
    @ns.doc('create_demo')
    @ns.expect(model, validate=True)  # validate checks the input is provided
    @ns.marshal_with(model, code=201)
    def post(self):
        '''Create demo'''
        return api.payload

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

【问题讨论】:

    标签: python flask api-doc flask-restx


    【解决方案1】:
    1. 这是预期的行为吗?

    是的,因为您的函数没有正确中止或返回任何内容。

    1. 是否可以返回更清晰的错误,如上图所示?我的理解是我对格式的定义应该做到这一点?

    是的,您可以像以前一样挽救错误,然后返回您自己的消息并确保使用 Flask 的 abort 正确中止它

    试试这个:

    from flask import Flask, abort
    
    
    def output(self, key, obj, **kwargs):
        try:
            return self.format(obj[key])
        except (ValueError, MarshallingError) as e:
            return abort(400,  f'Unable to marshal field. errors: [{key}: {str(e)}]')
    

    此示例的输出将是格式为 400 的错误:

    {
      "message": "Unable to marshal field. errors: [name: 'd' is not a valid DemoEnum]"
    }
    

    这不会影响来自expect 装饰器的错误消息,即。如果您在名称字段中输入 1,您将收到与以前相同的消息。

    【讨论】:

    • 我也想知道,你为什么需要这个类? flask_restx 具有用于字符串的pattern 属性和用于列表的enum 属性
    猜你喜欢
    • 2016-04-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-05
    • 2021-09-16
    • 1970-01-01
    相关资源
    最近更新 更多