Flask-RestX/Plus: Sort namespace in Swagger.

Obi kastanya
3 min readJan 16, 2024

Flask-RestX/Plus is a good framework to integrate your restful API with Swagger. The company I work for also uses it. They are a great tool. But recently, I realized something annoying.

“Swagger namespace is not ordered”

As a documentation, I can’t accept this. API documentation should be easy to read and help people understand the API functionality. Unordered means hard to navigate and hard to understand.

Only a few resources on the internet talk about this issue. If you came to this article, you may encounter the same problem. Let me help you.

Flask-RestX/Plus does not provide a method to order the namespace on Swagger (Until this time: 2024–02–16).

The namespace order depends on the order when we register the namespace.

Take a look at the following codes:

from flask import Flask
from flask_restx import Api

from config import AppConfig

from modules.login.route import ns as login_namespace
from modules.fish.route import ns as fish_namespace
from modules.cat.route import ns as cat_namespace
from modules.sheep.route import ns as sheep_namespace
from modules.dog.route import ns as dog_namespace


api = Api(
title="Pets Shop API",
version="1.0",
description="API for Pets Shop App",
doc="/doc",
authorizations={
"apikey":{
"type":"apiKey",
"in":"header",
"name":"token"
}
}

)

api.add_namespace(login_namespace, path='/login')
api.add_namespace(dog_namespace, path='/dog')
api.add_namespace(fish_namespace, path='/fish')
api.add_namespace(cat_namespace, path='/cat')
api.add_namespace(sheep_namespace, path='/sheep')


app =Flask(__name__)
app.config.from_object(AppConfig)
api.init_app(app)

if __name__=="__main__":
app.run(debug=True, port=5000)

That is a simple flask_restx configuration for my PetShop API.

Take a look at the following lines:

...
api.add_namespace(login_namespace, path='/login')
api.add_namespace(dog_namespace, path='/dog')
api.add_namespace(fish_namespace, path='/fish')
api.add_namespace(cat_namespace, path='/cat')
api.add_namespace(sheep_namespace, path='/sheep')
...

That is the order of our namespace on the swagger. This is what the Swagger UI looks like:

Manual ordering is acceptable and easier if you have small amounts of API. But in my case, I have a lot of features and it’s impossible to order all of them.

To solve this problem, we should override the Api class.

Then we should add a method to sort the namespace by the namespace name.

Each time we register a namespace, we should reorder the namespaces.

This is what the codes look like:

from flask_restx import Api as Api_

class Api(Api_):

def add_namespace(self, ns, path=None):
"""
This method registers resources from namespace for current instance of api.
You can use argument path for definition custom prefix url for namespace.

:param Namespace ns: the namespace
:param path: registration prefix of namespace
"""
if ns not in self.namespaces:
self.namespaces.append(ns)

self.sort_namespace() # add this line

if self not in ns.apis:
ns.apis.append(self)
if path is not None:
self.ns_paths[ns] = path

for r in ns.resources:
urls = self.ns_urls(ns, r.urls)
self.register_resource(ns, r.resource, *urls, **r.kwargs)

for name, definition in ns.models.items():
self.models[name] = definition
if not self.blueprint and self.app is not None:
self._configure_namespace_logger(self.app, ns)

# add this method
def sort_namespace(self):
"""Sort swagger UI sections based on namespace name."""
self.namespaces = sorted(self.namespaces, key=lambda ns: ns.name)

Now this is what the swagger looks like.

Now the namespace is ordered by the namespace name.

Perfect.

If you need to see the full code, visit my GitHub repository here.

--

--