flask_docs自定义树节点显示内容

flask_docs自定义树节点显示内容

需求描述

使用python的flask框架开发api时,发现了一个插件flask_docs,可以通过注释自动生成api文档,类似ava的swagger

flask-docs使用介绍,点击看作者kwkwc大佬原文

但是目前该插件不支持自定义树节点的大小标题,生成的文档难以让外人理解。
于是重写了里面方法,实现了树节点大小标题的自定义。

效果

在这里插入图片描述

优化逻辑

  • 父节点显示的是蓝图的路径,可以通给蓝图命别名的方式,重写显示父节点的代码,显示蓝图对应的别名。
  • 子节点是 <· method(注释)> 的形式,可以将他们换个位置,变成 < · 注释(method) > 的显示方式。

代码实现

逻辑实现

from flask_docs import ApiDoc

# 先声明树节点(父)配置,里面存蓝图的重命名,也可以直接用一个list,我用这个配置的原因是整合了蓝图和文档的配置
app.config.setdefault("API_DOC_MEMBER_RENAME", [])   
···
# 按app.config["API_DOC_MEMBER"]里面填写的顺序依次重命名
for item in ["2. 外观全景", "3. 楼宇设施", "4. 综合安防", "5. 信息设施", '1. 通用接口']
	app.config["API_DOC_MEMBER_RENAME"].append(item)

ApiDoc._get_api_data = get_api_data # 用自己重写的get_api_data替代插件里面的对应方法

重写的方法(长#符号中间的是重写的类容)。

def get_api_data(self):
    """
    重构flask_docs里面的对应方法,支持重命名树节点
    """
    from flask_docs import logger as apidocs_log, PROJECT_NAME
    data_dict = {}

    for rule in current_app.url_map.iter_rules():
        f = str(rule).split("/")[1]
        if f not in current_app.config["API_DOC_MEMBER"]:
            continue

        # f_capitalize = f.capitalize()
        #########################################
        #### 重写的内容,使用重命名赋值给f_capitalize
        index = current_app.config["API_DOC_MEMBER"].index(f)
        f_capitalize = app.config["API_DOC_MEMBER_RENAME"][index]
        #########################################
        if f_capitalize not in data_dict:
            data_dict[f_capitalize] = {"children": []}

        api = {
            "name": "",
            "name_extra": "",
            "url": "",
            "method": "",
            "doc": "",
            "doc_md": "",
            "router": f_capitalize,
            "api_type": "api",
        }

        try:
            func = current_app.view_functions[rule.endpoint]

            name = self._get_api_name(func)
            url = str(rule)
            method = " ".join([r for r in rule.methods if r in current_app.config["API_DOC_METHODS_LIST"]])
            if method:
                url = "{}\t[{}]".format(url, "\t".join(method.split(" ")))

            result = filter(
                lambda x: x["name"] == name,
                data_dict[f_capitalize]["children"],
            )
            result_list = list(result)
            if len(result_list) > 0:
                result_list[0]["url"] = result_list[0]["url"] + " " + url
                result_list[0]["url"] = " ".join(list(set(result_list[0]["url"].split(" "))))
                result_list[0]["method"] = result_list[0]["method"] + \
                    " " + method
                result_list[0]["method"] = " ".join(list(set(result_list[0]["method"].split(" "))))
                raise RuntimeError

            api["url"] = url
            api["method"] = method

            doc = self._get_api_doc(func)

            # doc = doc.replace('__resp_example__',requests.request('method',url))

            (
                api["doc"],
                api["name_extra"],
                api["doc_md"],
            ) = self._get_doc_name_extra_doc_md(doc)

			##############################################################
			#### 重写的内容,将小标题的括号内外换位置,如果括号里面的没有东西,显示原来的效果
            if api["name_extra"] == '':
                api["name"] = name
            else:
                api["name"] = api["name_extra"]
                api["name_extra"] = name
			##############################################################
			""" 这里是我的项目里面做的通过在线文档自动测试,以及自动填充在线文档。
            if YAMLCONFIG is not None and api["doc_md"].index('__resp_example__') >= 0:
                start = api["doc_md"].index(YAMLCONFIG.apidoc.publichost)
                end = api["doc_md"].index('```', start)
                url = api["doc_md"][start:end].replace(YAMLCONFIG.apidoc.publichost, YAMLCONFIG.apidoc.localhost)
                resp = requests.request(method, url)
                api["doc_md"] = api["doc_md"].replace('__resp_example__', resp.text)
			"""
        except Exception as e:
            apidocs_log.exception("{} error - {}".format(PROJECT_NAME, e))
        else:
            data_dict[f_capitalize]["children"].append(api)

        if data_dict[f_capitalize]["children"] == []:
            data_dict.pop(f_capitalize)
        else:
            data_dict[f_capitalize]["children"].sort(key=lambda x: x["name"])

    return data_dict


我的项目中的逻辑实现,将蓝图和文档的配置内置了,外面的调用变得简单:

def RegisterBlueprintAndDoc(bluePrintList, doc_title=None, doc_version=None):
    """ 
    flask配置文档成员,并注册蓝图 
    
        @bluePrintList:可以将蓝图对象放到list/tuple里面进行注册。也支持通过dict类型重命名Flask_Docs文档里面的树节点:{BluePrint_Object:"rename"}
        @doc_title: 在线文档的标题,如果使用yaml配置,会优先读取YAMLCONFIG.apidoc.title
        @doc_version: 在线文档的版本,如果使用yaml配置,会优先读取YAMLCONFIG.apidoc.version
    """
    nameList = []
    if type(bluePrintList) in (list, tuple):
        ···
    elif type(bluePrintList) == dict:
    	#### 主要看这里,注册蓝图和设置在线文档放在一起,方便使用
        app.config.setdefault("API_DOC_MEMBER_RENAME", [])
        for key, value in bluePrintList.items():
            CORS(key)  # 解决跨域问题
            app.register_blueprint(key, url_prefix="/{}".format(key.name))
            nameList.append(key.name)
            app.config["API_DOC_MEMBER_RENAME"].append(value)
        app.config["API_DOC_MEMBER"] = nameList
        ApiDoc._get_api_data = get_api_data
        #### 
    else:
        logger.error('registerBlueprint调用失败,参数类型不支持')
  	
  	# createApiDoc(doc_title, doc_version) # 优先读取yaml里面的配置设置文档,和本文无关,屏蔽
    ApiDoc(app, doc_title, doc_version) # 设置文档



# 注册蓝图,直接使用dict重命名蓝图,方便使用
API.RegisterBlueprintAndDoc({Panaroma: "2. 外观全景", BuildDevice: "3. 楼宇设施", Security: "4. 综合安防", InfoDevice: "5. 信息设施", Comm: '1. 通用接口'})

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值