Here's a self-contained, minimal, reproducible, example with my use case:
import uvicorn
from fastapi import FastAPI, APIRouter
items = {}
app = FastAPI()
router = APIRouter(prefix="/api")
items_router = APIRouter(prefix="/items", tags=["items"])
@items_router.post("/{id}")
def add_item(id: str):
items[id] = {"attachments": []}
return items[id]
@items_router.get("/{id}")
def get_item(id: str):
if not (item := items.get(id)):
return "error"
return item
items_attachment_router = APIRouter(prefix="/{id}", tags=["attachment"])
@items_attachment_router.post("/add")
def add_attachment(id: str, attachment: str):
if not (item := items.get(id)):
return "error"
item["attachments"].append(attachment)
return item
items_attachment_router2 = APIRouter()
@items_attachment_router2.post("/{id}/add2")
def add_attachment2(id: str, attachment: str):
if not (item := items.get(id)):
return "error"
item["attachments"].append(attachment)
return item
items_router.include_router(items_attachment_router)
items_router.include_router(items_attachment_router2, tags=["attachment2"])
router.include_router(items_router)
app.include_router(router)
if __name__ == "__main__":
uvicorn.run(app)
the routes of an APIRouter appear under the tags given by the router and all parent routers.
I implemented it the old and the new way (adding tags to the router directly & adding them as a param in include_router). Both methods put the routes add_attachment and add_attachment2 under their own tag and them items tag
FastAPI version 0.62.0
Sorry, can you explain what the issue is? It isn't clear from the information you have provided
Please describe the issue clearly or better to share a screenshot of the page you are getting issue with along with the clean description of your issue.
Hi,
sorry, the issue is that the routes appear twice (in swagger)
This is not a bug in fastapi, please see https://github.com/swagger-api/swagger-ui/issues/3711
Hi @Mause ,
thanks for your answer. In the thread you send multiple tags are added to the endpoints. In my case the motivation is to have a large API better structured.
Different modules, different ApiRouter objects, different tags. Still using hierarchies of routers for dependency purposes.
So routes in multiple locations doesnt help a lot to have the swagger page better sorted :)
So I see, after calling
I dont see exactly where fastapi puts these tags together.
in routing include_router there is
current_tags = []
if tags:
current_tags.extend(tags)
if route.tags:
current_tags.extend(route.tags)
but going through it with the debugger, there is no moment when I see the tags: _items_ and _attachment_ being put together.
Only at the point I call router.include_router(items_router) route.tags has both of them
So in order to fix this (for my app), any better way how I can change the tags of the routes than this:
...
items_router.include_router(items_attachment_router)
for route in items_router.routes:
if route.name in [r.name for r in items_attachment_router.routes]:
for tag in items_router.tags:
route.tags.remove(tag)
Maybe a parameter to the include_router could avoid this hack
I'm afraid I don't understand what you are trying to achieve - if you don't want a tag to be added, don't add it in the first place?
see what the hack made:
https://imagebin.ca/v/5lIfxYIs3VRX compared to the 1. one.
while still having the hierarchy of routers, which makes a bunch of things convinient
@transfluxus isn't it the expected behavior?
In the end, all of the routers extend your actual application and its OpenAPI spec.
... sure but this is about tags, and tags being passed down from one router to another...
Why does this being about tags change anything? Everything you have described so far is expected behaviour
k, what you would expect...
Its aruably reasonable to not have all routes in the api doc multiple times and only found a hack to to solve it.
So this is a feature request
If you do not wish for routes to appear multiple times in the Swagger UI, you must only have one tag per route. We do not control this behaviour, this is functionality built into Swagger UI, as I stated above