I'm trying to build an API using DRF with the following structure (example):
api/
├── v1/
│ ├── foo/
│ │ ├── bar/
│ │ │ └── urls.py # There's one `rest_framework.routers.DefaultRouter` here
│ │ ├── bar2/
│ │ │ └── urls.py # There's one `rest_framework.routers.DefaultRouter` here
│ │ ├── __init__.py
│ │ └── urls.py
│ ├── foo2/
│ │ ├── bar3/
│ │ │ └── urls.py # There's one `rest_framework.routers.DefaultRouter` here
│ │ ├── bar4/
│ │ │ └── urls.py # There's one `rest_framework.routers.DefaultRouter` here
│ │ ├── __init__.py
│ │ └── urls.py
│ ├── __init__.py
│ └── urls.py
├── __init__.py
└── urls.py
Intuitively, my endpoints would be
https://api.example.com/v1/foo/bar/...
https://api.example.com/v1/foo/bar2/...
https://api.example.com/v1/foo2/bar3/...
https://api.example.com/v1/foo2/bar4/...
But I want that Api Root
web page to be available from the https://api.example.com/v1
level. For example, when I ran curl https://api.example.com/v1
it would show me
{"foo":"https://api.example.com/v1/foo/","foo2":"https://api.example.com/v1/foo2/"}
and so on.
That being said, I guess that the way to do it was to somehow "merge" those DefaultRouter
s.
I'm aware that I could just router.registry.extend(some_other_router.registry)
, but that would make it all be at the same level and I explicitly needed it to be multi-level, as shown above.
I ended up writing an
IndexRouter
class, which then can be used as the following:urlpatterns
:You can also mix them. Besides, there are other useful parameters, such as:
name
: set the page name for breadcrumb navigationdeprecated_func
: a function that tells whether this endpoint is deprecated or not (drf-yasg
compatible)swagger_operation_description
:drf-yasg
compatible, see their docsswagger_operation_summary
:drf-yasg
compatible, see their docsThe implementation itself, although not really elegant, is the following: