mcpField
D
dmr

dmr

github.com/wemake-servicesDevelopment1.5k85 installsUpdated today
Repository

About dmr

dmr is a coding-agent skill for building and reviewing Django REST APIs with django-modern-rest. It guides typed controllers, routing, security, OpenAPI, and version-aware documentation use.

Key features

  1. 01Controller and request component guidance
  2. 02Sync and async endpoint checks
  3. 03Routing, auth, and throttling guidance
  4. 04OpenAPI generation from types
  5. 05Code review and testing checklist

Use cases

  1. 01Build Django REST APIs
  2. 02Review existing dmr code
  3. 03Verify endpoint and OpenAPI changes

Install

Copy the command and run it in a terminal.

$npx skills add https://github.com/wemake-services/django-modern-rest --skill dmr

After installing, type/dmrin Claude Code to confirm it loaded.

Bundled files

References and scripts installed along with SKILL.md.

.claude-plugin/
plugin.json
agents/
openai.yaml
references/
controllers.md
errors.md
openapi.md
routing.md
security.md
testing.md
validation.md

Details

From the project README

django-modern-rest (dmr)

django-modern-rest is a typed, sync-and-async REST layer for Django: Controller classes with one method per HTTP verb, DTOs parsed from Body, Query, Headers, Cookies, and Path annotations, Router based URLs, built-in auth and throttling, and OpenAPI generated from the types.

When to use

  • Any file that imports from dmr, or a project with django-modern-rest in its dependencies.
  • Requests for a "typed", "modern", or "async" Django REST API.
  • Reviews of existing dmr code: use the checklist at the end.

For migrations from other frameworks use dmr-from-drf, dmr-from-django-ninja, or dmr-from-dj-rest-auth. For version bumps use dmr-upgrade. For scaffolding from an OpenAPI document use dmr-openapi-skeleton.

Workflow

  1. Check the installed version and extras: uv pip show django-modern-rest (or the lock file). The API changes between minor releases, so read the docs for the installed version, not the latest one.
  2. Load the docs you need, they are versioned and LLM friendly:
    • index: https://django-modern-rest.readthedocs.io/en/<version>/llms.txt
    • one page as Markdown: replace .html with .md in any docs URL, for example https://django-modern-rest.readthedocs.io/en/latest/pages/routing.md
    • everything at once: https://django-modern-rest.readthedocs.io/en/<version>/llms.txt
  3. Read the reference for the area you are changing (see the table below), it holds the full rules with correct and wrong examples.
  4. Verify: run python manage.py check, the project's type checker, and tests written with the dmr_client / dmr_rf fixtures. For OpenAPI changes, run python manage.py dmr_export_schema <path> and review the diff.

Non-negotiable rules

Install django-modern-rest[msgspec] even for pydantic projects, it makes JSON parsing fastest. Add django-stubs[compatible-mypy] to dev dependencies, dmr relies on Django types.

Name component parameters exactly parsed_body, parsed_query, parsed_headers, parsed_path, and parsed_cookies. Other names are silently not parsed:

class UserController(Controller[MsgspecSerializer]):
    def post(self, parsed_body: Body[UserModel]) -> UserModel:
        return parsed_body

Optional components keep None inside the annotation: parsed_body: Body[UserModel | None] = None. Body[UserModel] | None = None is an import-time error.

Do not ever use return HttpResponse(...), because it bypasses negotiation, headers, cookies, and validation. Instead use self.to_response(...) or self.to_error(...) in controllers.

Raise APIError for errors, handle them in handle_error / handle_async_error, not in the endpoint body:

raise APIError(
    self.format_error('Not found', error_type=ErrorType.user_msg),
    status_code=HTTPStatus.NOT_FOUND,
)

Prefer @modify-styled endpoints to @validated-styled endpoints.

Use plain methods by default. Add @modify(...) only for a status code, headers, cookies, auth, throttling, or extra responses that differ from the inferred ones. Use @validate(ResponseSpec(...)) only when the endpoint returns an HttpResponse on purpose.

Prefer MsgspecSerializer. With pydantic and JSON only, prefer PydanticFastSerializer over PydanticSerializer.

Prefer BodyMsgspec over Body when MsgspecSerializer is used and all endpoint parsers decode into models, like MsgspecJsonParser and MsgpackParser.

Use dmr.routing.path and Router, and install build_404_handler / build_500_handler so API errors are JSON.

If CSRF and csrf_exempt = False are used always set CSRF_FAILURE_VIEW = build_csrf_handler(router.prefix, ...) error handler.

Keep validate_responses on in development and tests, turn it off only in production settings. Never disable semantic_responses, never set empty parsers or renderers.

Match sync and async: sync endpoints get sync error handlers and auth, async endpoints get async ones. Throttle login endpoints before auth.

Route auth endpoints from concrete_views with as_view(serializer=...), do not subclass dmr.security.*.views controllers only to restate the default payload and response. Subclass views only when the payload, the response, or a hook differs:

path(
    'auth/',
    concrete_views.ObtainTokensSyncController.as_view(
        serializer=MsgspecSerializer,
    ),
)

as_view silently ignores throttling= and auth=. Concrete views use Settings.throttling, a login-specific throttle needs a views subclass.

Test with dmr_rf (DMRRequestFactory) for unit tests and dmr_client (DMRClient) for full-stack tests, generate payloads with polyfactory, and use schemathesis against the OpenAPI schema.

Quick reference

TopicRulesRead
Controllers, @modify vs @validate, serializers, responses, components, redirects9references/controllers.md
Routing, 404 / 500 handlers, sync and async app layout4references/routing.md
Error handlers, APIError, custom error_model4references/errors.md
Response validation, HttpSpec, settings5references/validation.md
Ready-to-use auth concrete_views, typed authenticated requests, throttling, wrap_middleware4references/security.md
pytest style, DMRClient, DMRRequestFactory, polyfactory, schemathesis5references/testing.md
Docstrings as OpenAPI descriptions1references/openapi.md

Every rule links to the documentation page that explains it.

Review checklist

Flag these when reviewing dmr code:

  • A component parameter with a name other than parsed_*.
  • Body[Model] | None = None instead of Body[Model | None] = None.
  • HttpResponse(...) or JsonResponse(...) returned from an endpoint.
  • try / except returning error responses inside an endpoint body.
  • @modify or @validate that changes nothing compared to the defaults.
  • isinstance(exc, APIError) inside an error handler.
  • validate_responses = False outside production settings, semantic_responses disabled, or empty parsers / renderers.
  • A sync handle_error on an async controller, or the other way around.
  • RemoteAddr(runs_before_auth=False) on a login endpoint.
  • A subclass of an auth controller from dmr.security.*.views that keeps the default payload and response, where its concrete_views counterpart does the same.
  • Cookie concrete_views without jwt_refresh_cookie_path, so the refresh token is sent with every request.
  • throttling=, auth=, or responses= passed to as_view(), they are silently ignored there.
  • RedirectTo(next_url) with a user-provided URL and no url_has_allowed_host_and_scheme check.
  • django.urls.path where dmr.routing.path is a drop-in replacement.
  • django.test.TestCase, RequestFactory, or Client where the dmr_rf / dmr_client fixtures exist.
  • Controllers and endpoints without docstrings when OpenAPI is served.

Comments

Markdown supported