OpenApi

This library automatically generates an OpenAPI schema based on the type annotations defined in the application's endpoints.

In the examples, we will use the swagger-ui-py library to visualize the documentation generated by flask_typed_routes.

The generated schema is fully customizable to meet the specific needs of your application.

Additionally, the library offers the typed_route decorator, which enables fine-grained control over the various fields supported by OpenAPI to describe an operation. Detailed instructions on its usage can be found in the relevant sections of this documentation. Furthermore, the FlaskTypedRoutes class accepts keyword arguments (kwargs) corresponding to different OpenAPI configuration fields. These can be used to fully customize the application's schema and tailor it to specific requirements.

Note

The OpenAPI schema is generated automatically when the application is initialized. You can access the OpenAPI schema by calling the get_openapi_schema method of the FlaskTypedRoutes class.

Warning

Get the OpenAPI schema from the FlaskTypedRoutes instance after registering the routes and blueprints, as the extension first needs to collect the routes to generate the OpenAPI schema.

Basic Usage

Tip

Ensure that the swagger-ui-py library is installed to visualize the OpenApi schema.

pip install swagger-ui-py  # ignore if already installed
import flask
import flask_typed_routes as ftr
import pydantic
import swagger_ui


app = flask.Flask(__name__)
app_ftr = ftr.FlaskTypedRoutes(app=app)


class Item(pydantic.BaseModel):
    name: str
    price: float
    description: str = None


@app.get('/items/<user>/')
def read_items(user: str, skip: int = 0, limit: int = 10):
    data = {'user': user, 'skip': skip, 'limit': limit}
    return flask.jsonify(data)


@app.post('/items/')
def create_item(item: Item):
    return flask.jsonify(item.model_dump())


@app.put('/items/<item_id>/')
def update_item(item_id: int, item: Item):
    return flask.jsonify({'item_id': item_id, **item.model_dump()})


@app.delete('/items/<item_id>/')
def remove_item(item_id: int):
    return flask.jsonify({'item_id': item_id})


swagger_ui.api_doc(app, config=app_ftr.get_openapi_schema(), url_prefix='/docs')

In this example if you run the application and navigate to http://127.0.0.1:5000/docs, you will see the documentation generated by the swagger-ui-py library using the OpenApi schema generated by flask_typed_routes.

OpenApi Example

Using typed_route decorator

The typed_route decorator allows you to parameterize the fields supported by OpenApi to describe an operation.

import flask.views
import flask_typed_routes as ftr
import swagger_ui


app = flask.Flask(__name__)
app_ftr = ftr.FlaskTypedRoutes(app=app)


@app.get('/items/<item_id>/')
@ftr.typed_route(
    summary='Get item by ID',
    description='Get item by ID from the database by its ID.',
    tags=['items'],
)
def get_item(item_id: int):
    return flask.jsonify({'item_id': item_id})

swagger_ui.api_doc(app, config=app_ftr.get_openapi_schema(), url_prefix='/docs')

OpenApi Example

Customizing OpenAPI schema

For more advanced customization, you can pass additional parameters to the FlaskTypedRoutes class.

import flask.views
import flask_typed_routes as ftr
import pydantic
import swagger_ui


class Item(pydantic.BaseModel):
    name: str
    description: str = None
    price: float
    tax: float = None


app = flask.Flask(__name__)
app_ftr = ftr.FlaskTypedRoutes(
    app=app,
    openapi_version='3.1.1',
    title='My API',
    version='1.0.0',
    summary='This is a sample API',
    description='This is a sample API for demonstration purposes.',
    terms_of_service='https://example.com/terms/',
    contact_info={
        'name': 'API Support',
        'url': 'http://www.example.com/support',
        'email': 'support@gmail.com'
    },
    license_info={
        'name': 'Apache 2.0',
        'url': 'https://www.apache.org/licenses/LICENSE-2.0.html',
    },
    servers=[{"url": "/api/v3"}],
    webhooks=None,
    tags=[
        {
            "name": "items",
            "description": "Everything about your items",
        }
    ],
    components={
        "securitySchemes": {
            'item_auth': {
                "type": "oauth2",
                "flows": {
                    "implicit": {
                        "authorizationUrl": "https://example.com/authorization",
                        "scopes": {
                            "read:items": "read items",
                            "write:items": "write items"
                        }
                    }
                }
            },
            "api_key": {
                "type": "apiKey",
                "name": "api_key",
                "in": "header",
            }
        }
    },
    external_docs={
        "description": "Find out more about Swagger",
        "url": "http://swagger.io"
    },
)


@app.get('/items/<item_id>/')
@ftr.typed_route(
    status_code=200,
    tags=['items'],
    summary='Get an item',
    description='Get an item by ID',
    security=[{'item_auth': ['read:items']}, {'api_key': []}]
)
def read_item(item_id: int):
    return flask.jsonify({'item_id': item_id})


@app.put('/items/<item_id>/')
@ftr.typed_route(
    status_code=202,
    tags=['items'],
    summary='Update an item',
    description='Update an item by ID',
    security=[{'item_auth': ['write:items']}]
)
def update_item(item_id: int, item: Item):
    return flask.jsonify({'item_id': item_id, **item.model_dump()})


swagger_ui.api_doc(
    app,
    config=app_ftr.get_openapi_schema(),
    url_prefix='/docs'
)

OpenApi Example