代码
from enum import Enum
from apiflask import APIFlask
from apiflask.fields import Integer
from apiflask.validators import OneOf
app = APIFlask(__name__, docs_ui='elements')
class APIFlaskEnum(Enum):
@classmethod
def choices(cls):
return [i.value for i in cls]
@classmethod
def description(cls):
return '\n\n'.join(f'{i.value}={i.name}' for i in cls)
class CategoryEnum(APIFlaskEnum):
cat = 1
dog = 2
@app.get('/say')
@app.input(dict(
category=Integer(required=True, validate=OneOf(CategoryEnum.choices()))
), location='query')
@app.doc(description=CategoryEnum.description())
def say(data):
"""枚举值入参"""
return CategoryEnum(data['category']).name
if __name__ == '__main__':
app.run()
效果
以上为替代方案,但当参数有多个枚举类型时,该方案就不太适合了,有没有更优雅的方式解决呢?
还有一个是,要用两个\n才能显示出换行,有没有办法解决?
感谢!
greyli
August 13, 2022, 4:05am
#2
优雅的方式可能是等 marshmallow 内置 Enum 支持的 PR 合并……
marshmallow-code:dev
← marshmallow-code:enum
opened 02:11PM - 20 Jul 22 UTC
「当参数有多个枚举类型时」具体是指什么?没太明白。
要用两个\n才能显示出换行
description 可以用 Markdown,不过也都差不多。另外或许可以考虑把这个放到字段的 description 里面:
category = Integer(
required = True,
validate = OneOf(CategoryEnum.choices()),
metadata = {'description': CategoryEnum.description()}
)
1 Like
谢谢回复!希望 marshmallow 能早日添加这个 feature
理想的情况是,这样写就能生成参数为枚举值的文档:
@app.input(dict(
category=Integer(required=True, validate=OneOf(CategoryEnum))
), location='query')
根据建议优化了一下
from enum import Enum
from apiflask import APIFlask
from apiflask.fields import Integer
from apiflask.validators import OneOf
app = APIFlask(__name__, docs_ui='elements')
class APIFlaskEnum(Enum):
@classmethod
def choices(cls):
return [i.value for i in cls]
@classmethod
def description(cls):
desc = '<br>'.join(f'{i.value}={i.name}' for i in cls)
if cls.__doc__ and cls.__doc__ != 'An enumeration.':
desc = cls.__doc__ + '<br>' + desc
return desc
class CategoryEnum(APIFlaskEnum):
"""类别"""
cat = 1
dog = 2
@app.get('/say')
@app.input(dict(
category=Integer(required=True, validate=OneOf(CategoryEnum.choices()),
metadata={'description': CategoryEnum.description()})
), location='query')
def say(data):
"""枚举值入参"""
return CategoryEnum(data['category']).name
if __name__ == '__main__':
app.run()
效果
1 Like
好消息!marshmallow 3.18.0 已更新枚举字段 marshmallow.fields.Enum
安装
pip install -U marshmallow
示例代码
from enum import Enum
from marshmallow import Schema, fields
class CategoryEnum(Enum):
cat = 1
dog = 2
class Pet:
def __init__(self, name, category):
self.name = name
self.category = category
class PetSchema(Schema):
name = fields.String()
category = fields.Enum(CategoryEnum)
class PetByValueSchema(Schema):
name = fields.String()
category = fields.Enum(CategoryEnum, by_value=True)
pet = Pet(name='Kitty', category=CategoryEnum.cat)
print(PetSchema().dump(pet))
print(PetByValueSchema().dump(pet))
# {'name': 'Kitty', 'category': 'cat'}
# {'name': 'Kitty', 'category': 1}
print(PetSchema().load({'name': 'Kitty', 'category': 'cat'}))
print(PetByValueSchema().load({'name': 'Kitty', 'category': 1}))
# {'name': 'Kitty', 'category': <CategoryEnum.cat: 1>}
# {'name': 'Kitty', 'category': <CategoryEnum.cat: 1>}
API 代码
import enum
from apiflask import APIFlask
from apiflask.fields import Integer
from marshmallow.fields import Enum
class CategoryEnum(enum.Enum):
"""类别"""
cat = 1
dog = 2
app = APIFlask(__name__, docs_ui='elements')
@app.get('/name')
@app.input(dict(
category=Enum(CategoryEnum)
), location='query')
def name(data):
return str(data['category'])
@app.get('/value')
@app.input(dict(
category=Enum(CategoryEnum, by_value=Integer)
), location='query')
def value(data):
return str(data['category'])
if __name__ == '__main__':
app.run()
1 Like
greyli
September 25, 2022, 1:44pm
#6
试了一下,apispec 目前还没法正确为 Enum 字段解析 OpenAPI spec,估计还要等后续支持。
apispec 已更新枚举字段解析 enum2properties()
安装
pip install apispec==6.0.0
代码
from enum import Enum
from apispec import APISpec
from marshmallow import fields
from apispec.ext.marshmallow import MarshmallowPlugin
class MyEnum(Enum):
one = 1
two = 2
field = fields.Enum(MyEnum)
ma_plugin = MarshmallowPlugin()
spec = APISpec(title='', version='', openapi_version='3.0.3', plugins=(ma_plugin,))
ret = ma_plugin.converter.field2property(field)
print(ret)
# {'type': 'string', 'enum': 'one, two'}
1 Like
试了一下不能直接渲染出来,如果辉哥有空麻烦看看,感谢
安装最新的 apispec 即可
pip install apispec -U
代码
import enum
from apiflask import APIFlask
from apiflask.fields import Integer
from marshmallow.fields import Enum
class CategoryEnum(enum.Enum):
"""类别"""
cat = 1
dog = 2
app = APIFlask(__name__, docs_ui='elements')
@app.get('/name')
@app.input(dict(
category=Enum(CategoryEnum)
), location='query')
def name(data):
return str(data['category'])
@app.get('/value')
@app.input(dict(
category=Enum(CategoryEnum, by_value=Integer)
), location='query')
def value(data):
return str(data['category'])
if __name__ == '__main__':
app.run()
效果
stutao
December 1, 2022, 2:15am
#11
有幸和题主经历了一样的问题,区别的是我的需求是在reponse中,经历了和题主一样的过程,很巧就看到这篇帖子,然后静静等待辉总1.2.0 的发布 。