簡體   English   中英

Flask restx MarshallingError 格式不正確

[英]Flask restx MarshallingError incorrect formatting

問題上下文

在使用 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中輸入 integer 時,正如預期的那樣,我得到了一個很好的錯誤,如下所示。

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

但是,當我輸入一個不在我的枚舉中的值(例如“d”)時,我的format定義中似乎捕獲了錯誤,但是, MarshallingError並沒有像預期的那樣隱藏所有內部錯誤。 這是 output 的簡短片段。

<!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)
  1. 這是預期的行為嗎?

是的,因為您是 function 沒有正確中止或返回任何內容。

  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)}]')

此示例的 output 將是 400 錯誤格式:

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

這不會影響來自expect裝飾器的錯誤消息,即。 如果您在名稱字段中輸入 1,您將收到與以前相同的消息。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM