# Структура документа https://habr.com/ru/articles/776538/ # Как тестировать https://editor.swagger.io/ # Пример формата openapi ``` { "openapi": "3.0.0", "info": { "title": "Sample API with Pydantic", "version": "1.0.0" }, "paths": { "/items": { "post": { "summary": "Create a new item", "requestBody": { "required": True, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ItemInputModel" } } } }, "responses": { "201": { "description": "Item created successfully" }, "400": { "description": "Invalid input data" } } } } }, "components": { "schemas": { "ItemInputModel": { "type": "object", "properties": { "name": { "type": "string" }, "description": { "type": "string" } }, "required": ["name"] } } } } ``` Генерация json ``` def generate_openapi_spec(): spec = { "openapi": "3.0.0", "info": { "title": "Sample API with Pydantic", "version": "1.0.0" }, "paths": {}, "components": { "schemas": {} } } for rule in app.url_map.iter_rules(): if rule.endpoint != 'static': spec["paths"][rule.rule] = {} for method in rule.methods - {'OPTIONS', 'HEAD'}: view_function = app.view_functions[rule.endpoint] spec["paths"][rule.rule][method.lower()] = { "summary": view_function.__doc__, "responses": { "200": { "description": "Successful operation" } } } # Добавляем параметры запроса, если они есть parameters = [] for param in rule.arguments: parameters.append({ "name": param, "in": "path", "required": True, "schema": { "type": "string" } }) if parameters: spec["paths"][rule.rule][method.lower()]["parameters"] = parameters ``` ``` class Item(BaseModel): name: str description: Union[str, None] = None price: float tax: Union[float, None] = None class AnotherModel(BaseModel): field1: str field2: int def extract_args(model_cls): @wraps(func) def decorator(func): @wraps(func) def wrapper(*args, **kwargs): # Извлекаем аргументы из URL args_dict = request.args.to_dict() # Получаем параметры функции func_params = list(func.__annotations__.keys()) # Извлекаем только те аргументы, которые принимает функция extracted_args = {k: v for k, v in args_dict.items() if k in func_params} # Создаем экземпляр модели из данных JSON json_data = request.json if request.is_json else None model_instance = model_cls(**json_data) if json_data else None # Передаем аргументы в функцию return func(*args, **kwargs, **extracted_args, model=model_instance) return wrapper return decorator @app.route('/process', methods=['GET', 'POST']) @extract_args(Item) def process(arg1: int, arg2: int, model: Union[Item, AnotherModel] = None): if isinstance(model, Item): return jsonify({"arg1": arg1, "arg2": arg2, "item": model.dict()}) elif isinstance(model, AnotherModel): return jsonify( {"arg1": arg1, "arg2": arg2, "another_model": model.dict()}) else: return jsonify({"arg1": arg1, "arg2": arg2}) ```