Easily add Swagger UI to a plain Flask API project with an OpenAPI specification file
Tags: swagger, flask, python, api
Published: 2020-07-16 00:47:48


This is a simple guide on how to add Swagger UI to your plain flask API project **without using any additional libraries.**
As I wanted a way to get Swagger UI implemented in my POC work in order to quickly show the intended functions to stakeholders. And there was no simple way to do it. All the youtube videos or online articles pointed to using libraries like flask-swagger-ui or FastAPI etc. I didn’t want to use any of those and even the official Swagger UI recommends running it as a docker container, which is overkill for something so simple. So this is the way I managed to do it.

#### Step 1: Download Swagger UI GitHub repo

Download [Swagger UI from GitHub](https://github.com/swagger-api/swagger-ui/archive/master.zip) and extract it. We are basically interested in the [dist](https://github.com/swagger-api/swagger-ui/tree/master/dist) directory in this archive.

#### Step 2: Copy the files from `dist` to your project directory

- In your project directory create 2 directories `templates` and `static`
- Move `index.html` from `dist` to `templates` directory and rename it to `swaggerui.html`
- Inside `static` directory, create 3 more directories, `css`,`img` and `js`
- Move `.js` files from `dist` to `static/js`
- Move `.css` files from `dist` to `static/css`
- Move `.png` files from `dist` to `static/img`

Your project directory should now look like this
```
.
├── static
│   ├── css
│   │   └── swagger-ui.css
│   ├── img
│   │   ├── favicon-16x16.png
│   │   └── favicon-32x32.png
│   └── js
│       ├── swagger-ui-bundle.js
│       ├── swagger-ui-standalone-preset.js
│       └── swagger-ui.js
└── templates
    ├── swaggerui.html
```

#### Step 3: Edit swaggerui.html and replace all static url with Jinja2 template tags

```html
7    <link rel="stylesheet" type="text/css" href="{{ url_for('static', filename='css/swagger-ui.css') }}">
8    <link rel="icon" type="image/png" href="{{ url_for('static', filename='img/favicon-32x32.png') }}" sizes="32x32"/>
9    <link rel="icon" type="image/png" href="{{ url_for('static', filename='img/favicon-16x16.png') }}" sizes="16x16"/>
36   <script src="{{ url_for('static', filename='js/swagger-ui-bundle.js') }}"> </script>
37   <script src="{{ url_for('static', filename='js/swagger-ui-standalone-preset.js') }}"> </script>
```

#### Step 4: Write your API spec in OpenAPI format

- Go to [swagger editor](https://editor.swagger.io/) and write your API spec in YAML.
Here is a Sample API spec:


{% gist https://gist.github.com/sanjan/35dc5bc2c849776574ec3daeb66cb686 %}

- Go to `File` menu in Swagger editor and click on `Convert and save as JSON`
- Place the downloaded `openapi.json` file in your projects' `static` directory
- Update the reference for the source json file (line 42) in `swaggerui.html` file to refer to the spec file in static directory
```javascript     
url: "{{ url_for('static', filename='openapi.json') }}",
```

#### Step 5: Return `swaggerui.html` with flask render_template in your preferred route

- Create `hello_api.py` in your project directory with the following code

{% gist https://gist.github.com/sanjan/bdfb92a74b631dc4de66df750a743489 %}
- Run the app with command: `python3 hello_api.py` from your project directory
- Your SwaggerUI documentation should be accessible on http://localhost:5000/api/docs


> I have created a boilerplate flask app for anyone to use this setup with ease.

{% github https://github.com/sanjan/flask_swagger no-readme %}