Skip to content
Reference

ModelSerializer

ModelSerializer is a Django model base class that carries its own schemas, Python CRUD methods and hooks. For how to use it, see Schemas and Python CRUD.

Python
from ninja_aio import ModelSerializer, SchemaConfig

Schemas

Declare each kind with a SchemaConfig inside class Schemas:. The generated names below are for a model named Article.

Kind Schema attribute Generated name Used for
create create_schema articleSchemaIn Create request body
update update_schema articleSchemaPatch Update request body
read read_schema articleSchemaOut List, create and update responses
detail detail_schema articleDetailSchemaOut Retrieve response. Falls back to read
(automatic) related_schema articleSchemaRelated This model nested inside another model
Python
class Article(ModelSerializer):
    ...

    class Schemas:
        create = SchemaConfig(fields=["title", "body", "category"])
        update = SchemaConfig(optionals=[("title", str), ("body", str)])
        read = SchemaConfig(fields=["id", "title", "category"])

A kind you leave out has no schema (None), and its endpoint is not generated. See Schema generation for how fields become schemas.

Validators

Put Pydantic @field_validator and @model_validator methods on these inner classes:

Inner class Applies to
CreateValidators create schema
UpdateValidators update schema
ReadValidators read schema
DetailValidators detail schema

Schema attributes

Attribute Description
create_schema, update_schema, read_schema, detail_schema, related_schema The generated schema class, or None if the kind is not declared. Built on first access and cached
get_schema(kind, *, depth=1) Returns the schema for "create", "update", "read", "detail" or "related". depth (relation nesting) only applies to read and detail
clear_schema_cache() Drops the cached schemas of this class

Assign your own Schema subclass to an attribute, for example read_schema = ArticleOut, to replace the generated one.

Python methods

All methods are classmethods. request is keyword-only and optional in every method.

Sync Async Returns
create(data, *, request=None) acreate(...) Article
get(pk=None, *, request=None, optimize_for=None, **lookups) aget(...) Article
get_queryset(*, request=None, optimize_for=None) aget_queryset(...) QuerySet[Article]
update(target, data, *, request=None) aupdate(...) Article
destroy(target, *, request=None) adestroy(...) None
model_dump(instance, *, schema=None, strict=False) amodel_dump(instance, *, schema=None) dict (default: detail schema)
model_dumps(instances, *, schema=None, strict=False) amodel_dumps(instances, *, schema=None) list[dict] (default: read schema)
bulk_create(items, *, request=None) abulk_create(...) BulkResult[Article]
bulk_update(items, *, request=None) abulk_update(...) BulkResult[Article]
bulk_destroy(targets, *, request=None) abulk_destroy(...) BulkResult of primary keys

target is an instance or a primary key. optimize_for is "read" or "detail". The dump methods load missing relations with one query per relation. strict=True makes the sync dump raise ValueError instead of running any query.

create classmethod

Python
create(data: InputData, *, request: HttpRequest | None = None) -> ModelSerializerT

Create and return one model instance synchronously.

acreate async classmethod

Python
acreate(data: InputData, *, request: HttpRequest | None = None) -> ModelSerializerT

Create and return one model instance asynchronously.

get classmethod

Python
get(pk: PrimaryKey | None = None, *, request: HttpRequest | None = None, optimize_for: QueryPurpose | None = None, **lookups: Any) -> ModelSerializerT

Retrieve and return one model instance synchronously.

aget async classmethod

Python
aget(pk: PrimaryKey | None = None, *, request: HttpRequest | None = None, optimize_for: QueryPurpose | None = None, **lookups: Any) -> ModelSerializerT

Retrieve and return one model instance asynchronously.

update classmethod

Python
update(target: ModelSerializerT | PrimaryKey, data: InputData, *, request: HttpRequest | None = None) -> ModelSerializerT

Update and return one model instance synchronously.

aupdate async classmethod

Python
aupdate(target: ModelSerializerT | PrimaryKey, data: InputData, *, request: HttpRequest | None = None) -> ModelSerializerT

Update and return one model instance asynchronously.

destroy classmethod

Python
destroy(target: ModelSerializerT | PrimaryKey, *, request: HttpRequest | None = None) -> None

Destroy one model instance synchronously.

adestroy async classmethod

Python
adestroy(target: ModelSerializerT | PrimaryKey, *, request: HttpRequest | None = None) -> None

Destroy one model instance asynchronously.

model_dump classmethod

Python
model_dump(instance: ModelSerializerT, *, schema: SchemaType | None = None, strict: bool = False) -> dict[str, Any]

Serialize one instance, loading missing schema relations; strict=True never queries.

amodel_dump async classmethod

Python
amodel_dump(instance: ModelSerializerT, *, schema: SchemaType | None = None) -> dict[str, Any]

Serialize one instance, loading relations required by the schema.

model_dumps classmethod

Python
model_dumps(instances: Iterable[ModelSerializerT] | QuerySet[ModelSerializerT], *, schema: SchemaType | None = None, strict: bool = False) -> list[dict[str, Any]]

Serialize a collection with the read schema, one query per missing relation.

amodel_dumps async classmethod

Python
amodel_dumps(instances: Iterable[ModelSerializerT] | QuerySet[ModelSerializerT], *, schema: SchemaType | None = None) -> list[dict[str, Any]]

Serialize instances, loading relations required by the read schema.

Hooks

Sync viewsets call the plain names, async viewsets the a names. Override one of the pair. See Hooks.

Hook Signature Runs
queryset_request / aqueryset_request (cls, request) classmethod Builds the base queryset for lookups, lists, updates and deletes
post_create / apost_create (self) Once, after the object is created
custom_actions / acustom_actions (self, payload) On create and update, with the customs fields as a dict
on_create_before_save (self) Before the first save only
before_save (self) Before every save
on_create_after_save (self) After the first save only
after_save (self) After every save
on_delete (self) After the object is deleted
has_changed / ahas_changed (self, field) -> bool Helper: True if the value differs from the database
as_admin (cls, **overrides) -> type Helper: returns a Django ModelAdmin class built from the schemas

Query optimization

Declare class QuerySet: on the model to add select_related and prefetch_related to generated queries.

Attribute Type Description
read, detail, queryset_request, extras ModelQuerySetSchema (extras: list of ModelQuerySetExtraSchema) Relations to load for list, retrieve and the base queryset. detail falls back to read. extras adds named scopes
Python
from ninja_aio.schemas import ModelQuerySetSchema


class Article(ModelSerializer):
    ...

    class QuerySet:
        read = ModelQuerySetSchema(select_related=["category"])

NinjaAIOMeta

Optional inner class with names the framework uses instead of Django's Meta.

Key Default Description
verbose_name Meta.verbose_name Singular name, used in the OpenAPI tag
verbose_name_plural Meta.verbose_name_plural Plural name. Spaces become hyphens in the default URL path
not_found_name Model name Error text of 404 responses: {"error": "<not_found_name>"}
Python
class Article(ModelSerializer):
    ...

    class NinjaAIOMeta:
        verbose_name_plural = "blog posts"  # -> /api/blog-posts

See also