Features overview
1. Django 6.1 official support
It was released last week, now we are fully sure that DMR works with the most modern Django version.
2. Router.include() — compose routers
from dmr.routing import Router
api_v1 = Router()
api_v1.include(users_router, prefix="/users")
api_v1.include(orders_router, prefix="/orders")3. external_path() — mount external views
from dmr.routing import external_path
urlpatterns = [
external_path("webhook/", third_party_view),
]4. Skip controllers/endpoints from OpenAPI
from dmr import Controller
from dmr.plugins.msgspec import MsgspecSerializer
class InternalController(Controller[MsgspecSerializer]):
ignore_from_spec = True
def get(self) -> InternalStatus: ...5. extra_namespace in BaseSerializer.from_python
Now available on all serializers:
schema = PydanticSerializer.from_python(
MyModel,
extra_namespace={"MyForwardRef": MyForwardRef},
)6. Load external OpenAPI schemas into typed dataclasses
from dmr.openapi.openapi import OpenAPI
from dmr.openapi import load_schema
schema = load_schema(external_schema_dict, OpenAPI)7. --skip-validation flag for dmr_export_schema
python manage.py dmr_export_schema --skip-validation > openapi.json8. dmr.test.disabled_auth — speed up tests
from dmr.test import disabled_auth, DMRRequestFactory
def test_list_users(dmr_rf: DMRRequestFactory, user: User) -> None:
request = dmr_rf.get('/api/your-controller')
with disabled_auth(YourController, request=request, user=user):
response = YourController.as_view()(request)
assert response.status_code == 200Migration prompt
They cover all the breaking changes.
We had to make them, so the API would be top notch in the future.
There was a big overhaul of OpenAPI and routing in this release.
Now we can do a lot of amazing things easily. But, the cost was backward compatibility.
You are migrating a Python project from `django-modern-rest` 0.12.0 to 0.13.0.
Load the latest documentation from https://django-modern-rest.readthedocs.io/llms-full.txt
before making any changes.
Apply **all** of the following breaking changes to the codebase.
For each change, search the entire project (including tests, fixtures, and
any helper modules) before editing.
---
### 1. `Schema.then` → `Schema.schema_then`
Find every attribute access or contructor param`then` on a `Schema` class
or instance and rename it to `schema_then`.
Before:
Schema(then=...)
schema.then
After:
Schema(schema_then=...)
schema.schema_then
---
### 2. `dmr.openapi.objects.openapi.convert` → `dmr.openapi.mappers.schema_normalization.dump_schema`
Find all imports and call-sites of `convert` from
`dmr.openapi.objects.openapi` and replace them:
Before:
from dmr.openapi.objects.openapi import convert
convert(...)
After:
from dmr.openapi.mappers.schema_normalization import dump_schema
dump_schema(...)
---
### 3. Remove `normalize_key` and `normalize_value`
Find all imports and usages of `normalize_key` and `normalize_value`
from `dmr.openapi.objects.openapi` and remove them entirely.
These functions have been deleted with no replacement.
If they are called inline, investigate whether the call site can be
removed or rewritten without them (consult the updated docs).
Use `dump_schema` directly instead.
Before:
from dmr.openapi.objects.openapi import normalize_key, normalize_value
After:
# remove the import and all call sites
---
### 4. `dmr.openapi.objects.openapi.ConvertedSchema` → `dmr.openapi.mappers.schema_normalization.DumpedSchema`
Before:
from dmr.openapi.objects.openapi import ConvertedSchema
After:
from dmr.openapi.mappers.schema_normalization import DumpedSchema
Replace all type annotations, isinstance checks, and other usages
of `ConvertedSchema` with `DumpedSchema`.
---
### 5. Remove `dmr.openapi.views.base.DumpedSchema`
Find all imports of `DumpedSchema` from `dmr.openapi.views.base` and remove
them. It was a plain `str` type alias; replace any annotation that used it
with the built-in `str`.
Before:
from dmr.openapi.views.base import DumpedSchema
def foo() -> DumpedSchema: ...
After:
def foo() -> str: ...
---
### 6. `dmr.openapi.objects.OpenAPI` → `dmr.openapi.openapi.OpenAPI`
Before:
from dmr.openapi.objects import OpenAPI
After:
from dmr.openapi.openapi import OpenAPI
---
### 7. `rebuild_namespace` → `extra_namespace` in `PydanticSerializer.from_python`
Find every call to `PydanticSerializer.from_python(...)` that passes a
`rebuild_namespace` keyword argument and rename the parameter.
Before:
PydanticSerializer.from_python(..., rebuild_namespace=ns)
After:
PydanticSerializer.from_python(..., extra_namespace=ns)
---
### 8. `skip_validation` must be keyword-only on `OpenAPIView.as_view()` and subclasses
Find all call sites of `.as_view()` on `OpenAPIView` or any of its
subclasses where `skip_validation` is passed as a positional argument and
make it explicit.
Before:
MyOpenAPIView.as_view(schema, True) # skip_validation passed positionally
After:
MyOpenAPIView.as_view(schema, skip_validation=True)
Also update any subclass overrides of `as_view` so that `skip_validation`
appears after a bare `*` in the signature:
Before:
@classmethod
def as_view(cls, skip_validation=False, **kwargs): ...
After:
@classmethod
def as_view(cls, *, skip_validation=False, **kwargs): ...
---
### 9. `Controller.get_path_item` → `Controller.get_schema`
Find every definition and call site of `get_path_item` on any
`Controller` subclass and rename it to `get_schema`.
Before:
class MyController(Controller):
def get_path_item(self, router): ...
controller.get_path_item(router)
After:
class MyController(Controller):
def get_schema(self, router): ...
controller.get_schema(router)
---
### 10. Remove `dmr_assert_throttling` and `dmr_assert_async_throttling` pytest fixtures
These are no longer fixtures. Find every use of them as pytest fixtures
(i.e. as function parameters in test functions) and replace them with
direct function calls instead.
Before:
def test_my_endpoint(dmr_assert_throttling):
dmr_assert_throttling(client, url)
After:
from dmr.test.throttling import assert_throttling # adjust import as needed
def test_my_endpoint():
assert_throttling(client, url)
Do the same for `dmr_assert_async_throttling`.
---
### 11. Remove `dmr.test.types` module
Find all imports from `dmr.test.types` and replace them with the new
location:
Before:
from dmr.test.types import ThrottlingWhen
After:
from dmr.test.throttling import ThrottlingWhen
Any other symbols that were imported from `dmr.test.types` should be
investigated; if they no longer exist, remove them.What's Changed
Breaking changes
Since this release, we would only publish migration prompts
on the releases page: https://github.com/wemake-services/django-modern-rest/releases
Schema.thenis renamed to beSchema.schema_then
to be consistent with other similar names, #1221dmr.openapi.objects.openapi.convertfunction is renamed and moved
todmr.openapi.mappers.schema_normalization.dump_schema, #1221dmr.openapi.objects.openapi.normalize_key
anddmr.openapi.objects.openapi.normalize_valuefunctions are removed, #1221dmr.openapi.objects.openapi.ConvertedSchemais renamed and moved
todmr.openapi.mappers.schema_normalization.DumpedSchema, #1221dmr.openapi.views.base.DumpedSchemais removed,
it was just astrtype alias, #1221dmr.openapi.objects.OpenAPIis moved
todmr.openapi.openapi.OpenAPI, #1222rebuild_namespaceparameter inPydanticSerializer.from_python
was renamed toextra_namespace, #1222- Changed
skip_validationparameter to be kw-only
onOpenAPIView.as_view()and all its subclasses, #1229 - Renamed
dmr.controller.Controller.get_path_itemto
get_schema, so all methods will be consistent, #1238 - Removed
dmr_assert_throttlinganddmr_assert_async_throttling
fixtures frompytest, because there was ever no need to make them fixtures,
use regular functions instead, #1245 - Removed
dmr.test.typesmodule, because it was only needed
fordmr_pytestthrottling fixtures, #1245 - Moved
dmr.test.types.ThrottlingWhentodmr.test.throttling, #1245
Features
- Django 6.1 official support, #1214
- Added
--skip-validationto thedmr_export_schemamanagement command, #1225 - Added
extra_namespaceparameter toBaseSerializer.from_python
and all its existing subclasses, #1222 - Added an ability to load external OpenAPI schemas
into our typed dataclasses, #1222 - Added
external_path()function, so we can load external views, #1239 - Added
Router.include()method to include one router into another one, #1244 - Added an option to skip some controllers / endpoints
from the OpenAPI spec, #1238 - Added
dmr.test.disabled_authtest helper
to disable auth to speed up tests, #1216
Bugfixes
- Fixed a bug that
OpenAPIConfig.componentswere silently
ignored when defined with custom user's data, #1229 - Fixed missing
$ref,$anchor,$comment, and$schemafields inSchema, #1232 - Fixed
OpenAPIFormat.IRIvalue, #1228
Misc
- Improved testing docs, #1216
New Contributors
- @Lancetnik made their first contribution in #1196
- @AsilbekKha made their first contribution in #1200
- @JuliaBars made their first contribution in #1218
- @aryansk made their first contribution in #1227
- @erensh27 made their first contribution in #1228
- @chirizxc made their first contribution in #1235
- @Sabfo made their first contribution in #1237
- @ShlokShar made their first contribution in #1241
Full Changelog: 0.12.1...0.13.0