- install mergedeep
pip install mergedeep
- adapter/hooks.py
from collections.abc import MutableMapping
from dmr.openapi import build_schema
from mergedeep import merge
from dmr_demo_api.apps.openapi.config import get_config
from dmr_demo_api.urls import router
def dmr_adapter_hook(*, result: dict, generator, **_kwargs) -> MutableMapping:
openapi_schema = build_schema(router, config=get_config())
schema = openapi_schema.convert()
return merge(schema, result)- Using hook / Использование адаптера
SPECTACULAR_SETTINGS = {
...
"POSTPROCESSING_HOOKS": ["adapter.hooks.dmr_adapter_hook"],
}There are many projects in the world created using the Django Rest Framework (DRF). Many of them have already migrated to the latest versions of python and django. The only thing left is to switch to Django Modern Rest (dmr). But it's very difficult to do this, so you need to be able to make a smooth transition. In other words, you need to allow writing new APIs on dmr without rewriting the entire existing DRF API. This is prevented by the public interface - swagger/openapi. DRF has its own, and dmr has its own. No self-respecting company will make its users suffer by forcing them to use two swagger UI.
You can create an adapter that allows you to connect dmr to an existing project with a stack of django + drf + spectacular.
As long as DRF is live in the project, the entire API will be available through its spectacular interface.
When the entire API is rewritten to dmr, it will be possible to switch to the new interface and throw out the DRF + spectacular bundle.
It seems that combining DRF and dmr in one project is not the most reasonable solution, because developers will have to work with two radically different approaches. But this is offset by the fact that the risks associated with using the new technology are insured by having a reliable and proven backup option at hand. At the same time, the potential benefits of using dmr are great.
The problem of a smooth transition from DRF exists in other frameworks as well:
Perhaps no one needs a smooth transition. Or maybe no one thought about it, and whoever first suggests it will get the maximum commercial advantage.
- A separate library. Pros: it doesn't clog up the dmr code. Cons: You need to promote it separately so that those who need it can find out about it; someone needs to maintain this library.
- As part of the dmr. Advantages: The target audience shared with dmr, the fastest possible promotion and implementation. When DRF drops, it can be moved to a separate library. Cons: it is only indirectly related to dmr.
- As part of drf-spectacular. DRF-spectacular has a special folder for such things. Pros: the most logical solution. Cons: no one will know that there is a new adapter; no one will be involved in support.
This project is a proof-of-concept showing how to write a dmr - spectacular adapter.
The implementation is as naive as possible, based on the assumption that the swagger dmr interface is also published at some url.
Unfortunately, I don't have time for a full-fledged project with documentation and tests.
В мире существуют множество проектов созданных с использованием Django Rest Framework (DRF). Многие из них уже перешли на свежие версии python и django. Осталось дело за малым, перейти на Django Modern Rest (dmr). Но сделать это резко сложно, поэтому нужна возможность плавного перехода. Т.е. нужно позволить писать новые API на dmr, не переписывая весь существующий DRF-API. Этому препятствует публичный интерфейс - swagger/openapi. У DRF он свой, а у dmr - свой. Ни одна уважающая себя компания не заставит своих пользователей страдать, заставляя использовать два swagger ui.
Можно создать адаптер, который позволяет подключить dmr в существующий проект со стеком django + drf + spectacular.
Пока в проекте будет жить DRF, весь API будет доступен через его интерфейс spectacular.
Когда весь API будет переписан на dmr, можно будет переключиться на новый интерфейс и выкинуть связку DRF + spectacular.
Кажется, что совмещение DRF и dmr в одном проекте это не самое разумное решение, т.к. разработчикам придётся работать с двумя кардинально различными подходами. Но это компенсируется тем, риски связанные с использованием новой технологии, подстрахованы наличием под рукой надёжного и проверенного запасного варианта. При этом потенциальный выигрыш от использования dmr велик.
Проблема плавного перехода с DRF есть и в других фреймворках:
Возможно, плавный переход никому не нужен. А возможно, об этом никто не думал, и тот, кто первый такое предложит, тот и получит максимальное коммерческое преимущество.
- Отдельная библиотека. Плюсы: не засоряет код dmr. Минусы: Нужно отдельно её продвигать, чтобы те, кто в ней нуждаются, могли о ней узнать; кто-то должен поддерживать эту библиотеку
- В составе dmr. Плюсы: Общая с dmr целевая аудитория, максимально быстрое продвижение и внедрение. Когда DRF падёт, можно вынести в отдельную библиотеку. Минусы: имеет только косвенное отношение к dmr.
- В составе drf-spectacular. У drf-spectacular есть специальная папка для таких вещей. Плюсы: самое логичное решение. Минусы: никто не узнает, что там появился новый адаптер; никто не будет заниматься поддержкой.
Данный проект - proof-of-concept показывающий как можно написать адаптер dmr - spectacular.
Реализация максимально наивная
К сожалению, времени на полноценный проект, с документацией и тестами, у меня нет.
git clone https://github.com/gimntut/spectacular-dmr-demo.git
cd spectacular-dmr-demo/
uv run src/manage.py migrateuv run src/manage.py runserver- http://localhost:8000/api/schema/swagger-ui/ - объединённый swagger
- http://localhost:8000/api/dmr/docs/swagger/ - dmr-swagger
src/adapter/hooks.py- файл с кодом адаптераsrc/config/settings/s20_applicaton.py- файл настроек, в котором происходит подключение
SPECTACULAR_SETTINGS = {
...
# !!! Вот здесь происходит подключение адаптера !!!
"POSTPROCESSING_HOOKS": ["adapter.hooks.dmr_adapter_hook"],
}