Skip to content
Guide

Field selection

This page shows how to let clients pick the fields of the response with ?fields=.

Add the mixin

Put FieldSelectionViewSetMixin before APIViewSet:

blog/api.py
from ninja_aio import NinjaAIO, APIViewSet
from ninja_aio.views.mixins import FieldSelectionViewSetMixin

from .models import Article

api = NinjaAIO(title="Blog API")


@api.viewset(model=Article)
class ArticleViewSet(FieldSelectionViewSetMixin, APIViewSet):
    pass

The list and retrieve endpoints now accept a fields query parameter. The other endpoints don't change. The mixin works the same in sync and async viewsets.

Request some fields

Send a comma-separated list of field names:

Text Only
GET /api/articles?fields=id,title
JSON
{
  "items": [
    {"id": 1, "title": "Hello Django"},
    {"id": 2, "title": "Async views"}
  ],
  "count": 2
}

The list keeps its items and count keys. Each item only has the fields you asked for.

The retrieve endpoint works the same way:

Text Only
GET /api/articles/1?fields=id,title
JSON
{"id": 1, "title": "Hello Django"}
Endpoint Fields you can pick
GET /api/articles The fields of the read schema
GET /api/articles/{id} The fields of the detail schema, or read when there is no detail

Selection works on the top-level fields. A relation, like category, comes back as the whole nested object or id.

Unknown fields

Names that are not in the schema are ignored:

Request Response
?fields=id,title Only id and title
?fields=title,password Only title
?fields=password The full response
?fields= The full response
No fields The full response

When none of the names is valid, you get the full response. Unknown names never return an error.

Combine with filters and pagination

fields works with filters, ordering and pagination. Put all the mixins before APIViewSet:

Python
from ninja_aio.views.mixins import FieldSelectionViewSetMixin, IcontainsFilterViewSetMixin


@api.viewset(model=Article)
class ArticleViewSet(FieldSelectionViewSetMixin, IcontainsFilterViewSetMixin, APIViewSet):
    query_params = {"title": (str, None)}
    ordering_fields = ["views", "title"]
Text Only
GET /api/articles?title=django&ordering=-views&page=1&page_size=10&fields=id,title

Filters, ordering and pagination run first. Then each item is cut down to id and title. count is the number of articles that match the filters.

The fields value is never passed to query_params_handler.

Rename the parameter

Set fields_param to use another name, for example when your model has a field called fields:

Python
@api.viewset(model=Article)
class ArticleViewSet(FieldSelectionViewSetMixin, APIViewSet):
    fields_param = "only"
Text Only
GET /api/articles?only=id,title
GET /api/articles/1?only=title

See also