π Release Notes
π·οΈ [v2.33.0] - 2026-06-26
β¨ New Features
ποΈ FieldSelectionViewSetMixin β Dynamic Field Selection via ?fields=
ninja_aio/views/mixins.py
FieldSelectionViewSetMixin adds a ?fields= query parameter to list and retrieve endpoints, letting clients request only the fields they need. Unrequested fields are stripped from the response without altering the declared Pydantic schema.
from ninja_aio.views import APIViewSet, mixins
class ArticleViewSet(mixins.FieldSelectionViewSetMixin, APIViewSet):
model = Article
schema_out = ArticleOut
schema_in = ArticleIn
schema_update = ArticlePatchClients can then filter fields per request:
GET /api/articles/?fields=id,title
GET /api/articles/42/?fields=id,title,authorBehaviour:
- Unknown field names are silently ignored
- If all requested fields are unknown, the full response is returned
- Field selection is post-serialization β the queryset is not modified
- The
?fieldsparameter does not interfere with filter mixins (e.g.IcontainsFilterViewSetMixin) - The mixin is composable with
PermissionViewSetMixin, filter mixins, and other mixins in any order
How it works: When a valid ?fields value is detected, the mixin returns a JsonResponse directly instead of a Status tuple. Django Ninja passes HttpResponse subclasses through without Pydantic re-validation, so partial dicts do not break strict schema checks. The OpenAPI docs continue to show the full schema.
The _fields_param class attribute ("fields" by default) can be overridden if the name conflicts with a model field.
class MyViewSet(mixins.FieldSelectionViewSetMixin, APIViewSet):
_fields_param = "select" # use ?select=id,name instead
...β‘ @on β Detail Action Shorthand with Auto Object Prefetch
ninja_aio/decorators/actions.py
@on is a new decorator for defining detail actions on APIViewSet that automatically fetches the target object before calling the handler. Unlike @action(detail=True), the handler receives the model instance directly β no manual get_object_or_404 required.
from ninja_aio.decorators import on
from ninja_aio.views import APIViewSet
class ArticleViewSet(APIViewSet):
model = Article
schema_out = ArticleOut
schema_in = ArticleIn
schema_update = ArticlePatch
@on("publish", methods=["post"])
async def publish(self, request, obj):
obj.status = "published"
await obj.asave(update_fields=["status"])
return Status(200, {"message": "published", "id": obj.id})
@on("archive", methods=["patch"], url_path="move-to-archive")
async def archive(self, request, obj):
obj.status = "archived"
await obj.asave(update_fields=["status"])
return Status(200, {"message": "archived"})What @on does automatically:
- Registers the endpoint as a detail action (URL includes
/{pk}/) - Calls
on_before_operation(request, action_name)before any other work - Fetches the model instance by pk via
get_objectβ raises 404 if not found - Calls
on_before_object_operation(request, action_name, obj)with the fetched instance - Passes the instance as
objto your handler
Parameters:
| Parameter | Type | Default | Description |
|---|---|---|---|
action_name |
str |
required | Name of the action (used as url_path by default) |
methods |
list[str] |
["post"] |
HTTP methods to register |
url_path |
str | None |
action_name |
URL path segment after /{pk}/ |
auth |
any | NOT_SET |
Override default authentication |
response |
any | NOT_SET |
Override response schema |
tags |
list[str] | None |
None |
OpenAPI tags |
summary |
str | None |
None |
OpenAPI summary |
description |
str | None |
None |
OpenAPI description |
deprecated |
bool |
False |
Mark as deprecated in OpenAPI |
@on vs @action:
@action |
@on |
|
|---|---|---|
| Object pre-fetch | β manual | β automatic |
| Hook chain | β | β |
| Default method | get |
post |
detail |
configurable | always True |
| Handler receives | request, **kwargs |
request, obj |
π Documentation
docs/api/views/mixins.mdβ newFieldSelectionViewSetMixinsection with attribute reference, tabbed examples, composability notes, and OpenAPI behaviourdocs/api/views/decorators.mdβ new@onsection with parameter table,@onvs@actioncomparison, and worked examples
π― Summary
v2.33.0 adds two quality-of-life features for APIViewSet users: field selection and object-aware detail actions.
FieldSelectionViewSetMixin lets API clients trim response payloads on the fly without any per-field schema boilerplate β useful for mobile clients, dashboards, or any consumer that only needs a subset of a large model's fields.
@on removes the repetitive pattern of pk-lookup + permission check + object fetch from custom detail actions. Declare the handler, receive the object, do the work β the framework handles the rest.
Key benefits:
- ποΈ Field selection β
?fields=id,nameon any list or retrieve endpoint, zero schema changes required - β‘
@onshorthand β detail actions receive the model instance directly, with full hook chain support - π Composable β both features work alongside existing mixins (
PermissionViewSetMixin, filter mixins, etc.) - π OpenAPI-accurate β full schema is always visible in docs regardless of runtime field filtering
- π‘οΈ 404 by default β
@onraisesNotFoundErrorautomatically when the pk is not found