0

我正在使用带有flask 1.1.2、apispec 5.1.1、marshmallow 数据类8.3.2 和flask_apispec 0.11.0 的python 3.8。基本代码如下所示: 我有一个对象(项目)的 marshamlow 数据类,该对象(项目)包含一个可选对象(所有者)。然后,对于我的最终端点,我需要发送这些项目的列表。

下面是一个最小的工作示例,一个端点获取具有可选所有者的项目,一个端点获取项目列表(具有可选所有者)。项目端点的 swagger 文档显示了所有者及其特征。投资组合的端点无法正确呈现 swagger 文档,并且仅显示所有者的空括号。我不知道这是否是 a)按预期工作(我只是不应该嵌套对象),b)apispec 的渲染问题或 c)由 flask_apispec 引起的(swagger.json)组合问题,并且会感谢任何人指出我为什么它不起作用的方向。

我尝试过使用 OpenApi 2.0 和 3.0 标准,但两者都遇到了同样的问题。对于值得验证的内容和实际的 API 行为似乎按预期工作,这只是一个招摇的问题

最小代码示例:

from typing import Optional

from apispec import APISpec
from apispec.ext.marshmallow import MarshmallowPlugin
from flask_apispec.extension import FlaskApiSpec
from flask_apispec import use_kwargs
from flask import Flask, request
from marshmallow_dataclass import dataclass, List
@dataclass
class Owner:
    email: str = field(metadata={'example': 'ac@d.com', 'default': 'b@g.com'})
    age: int = field(metadata={'example': 12, 'default': 12})
    name: str = field(metadata={'example': 'me', 'default': 'bla'})
@dataclass
class Item:
    color: str
    owner: Optional[Owner]
@dataclass
class PortfolioOfItems:
    assets: List[Item] = field(metadata={'default_factory': lambda: []})
    purchase_year: int
def create_app():
    app = Flask(__name__)
    apispecs = APISpec(
        title='api',
        version='2.3',
        openapi_version="3.0.0",
        plugins=[MarshmallowPlugin()],
    )
    app.config.update({
        'APISPEC_SPEC': apispecs,
        'APISPEC_SWAGGER_URL': '/swagger.json',
        'APISPEC_SWAGGER_UI_URL': '/apidocs/'
    })
    portfolio_schema = PortfolioOfItems.Schema()
    item_schema = Item.Schema()
    @use_kwargs(portfolio_schema)
    @app.route("/v1/portfolio", methods=["POST"])
    def portfolio():
        input_data = portfolio_schema.loads(request.data)
        owners = [i.owner for i in input_data if hasattr(i, 'owner')]

        result = {"result": owners}
        return result
    @use_kwargs(item_schema)
    @app.route("/v1/item", methods=["POST"])
    def item():
        print(request.data)
        input_data = item_schema.loads(request.data)
        owner = getattr(input_data, 'owner', None)
        result = {"result": owner}
        return result
    docs = FlaskApiSpec(app)
    docs.register(portfolio)
    docs.register(item)
    return app
if __name__ == '__main__':
    api = create_app()
    api.run(port=4999)

swagger 文档为 v1/item 正确呈现: 项目端点的大摇大摆输出

但是所有者在投资组合的描述中是空的大括号: 投资组合端点的招摇输出

为 swagger 文档生成的 json 文件(openapi 3.0):

  "components": {
    "schemas": {
      "Item": {
        "properties": {
          "color": {
            "type": "string"
          }, 
          "owner": {
            "allOf": [
              {
                "$ref": "#/components/schemas/Owner"
              }
            ], 
            "default": null, 
            "nullable": true
          }
        }, 
        "required": [
          "color"
        ], 
        "type": "object"
      }, 
      "Owner": {
        "properties": {
          "age": {
            "example": 12, 
            "type": "integer"
          }, 
          "email": {
            "example": "ac@d.com", 
            "type": "string"
          }, 
          "name": {
            "example": "me", 
            "type": "string"
          }
        }, 
        "required": [
          "age", 
          "email", 
          "name"
        ], 
        "type": "object"
      }, 
      "PortfolioOfItems": {
        "properties": {
          "assets": {
            "items": {
              "$ref": "#/components/schemas/Item"
            }, 
            "type": "array"
          }, 
          "purchase_year": {
            "type": "integer"
          }
        }, 
        "required": [
          "assets", 
          "purchase_year"
        ], 
        "type": "object"
      }
    }
  }, 
  "info": {
    "title": "api", 
    "version": "2.3"
  }, 
  "openapi": "3.0.0", 
  "paths": {
    "/v1/item": {
      "options": {
        "parameters": [
          {
            "in": "body", 
            "name": "body", 
            "required": false, 
            "schema": {
              "$ref": "#/components/schemas/Item"
            }
          }
        ], 
        "responses": {}
      }, 
      "post": {
        "parameters": [
          {
            "in": "body", 
            "name": "body", 
            "required": false, 
            "schema": {
              "$ref": "#/components/schemas/Item"
            }
          }
        ], 
        "responses": {}
      }
    }, 
    "/v1/portfolio": {
      "options": {
        "parameters": [
          {
            "in": "body", 
            "name": "body", 
            "required": false, 
            "schema": {
              "$ref": "#/components/schemas/PortfolioOfItems"
            }
          }
        ], 
        "responses": {}
      }, 
      "post": {
        "parameters": [
          {
            "in": "body", 
            "name": "body", 
            "required": false, 
            "schema": {
              "$ref": "#/components/schemas/PortfolioOfItems"
            }
          }
        ], 
        "responses": {}
      }
    }
  }```
4

0 回答 0