Skip to content

v2.33.0

Latest

Choose a tag to compare

@caspel26 caspel26 released this 26 Jun 16:20

πŸ“‹ 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 = ArticlePatch

Clients can then filter fields per request:

GET /api/articles/?fields=id,title
GET /api/articles/42/?fields=id,title,author

Behaviour:

  • 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 ?fields parameter 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 obj to 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 β€” new FieldSelectionViewSetMixin section with attribute reference, tabbed examples, composability notes, and OpenAPI behaviour
  • docs/api/views/decorators.md β€” new @on section with parameter table, @on vs @action comparison, 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,name on any list or retrieve endpoint, zero schema changes required
  • ⚑ @on shorthand β€” 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 β€” @on raises NotFoundError automatically when the pk is not found