Python Mixins — API Reference
ImplMixin
Abstract base. Subclasses must implement all perform_* methods.
python
class ImplMixin(Generic[K, T], ABC):
async def perform_create(self, context: Context, data: T) -> T: ...
async def perform_bulk_create(self, context: Context, data: list[T]) -> list[T]: ...
async def perform_list(self, context: Context) -> list[T]: ...
async def perform_retrieve(self, context: Context, pk: K) -> T: ...
async def perform_update(self, context: Context, pk: K, data: T, partial: bool = True) -> T: ...
async def perform_bulk_update(self, context: Context, records: dict[K, T], partial: bool = True) -> list[T]: ...
async def perform_destroy(self, context: Context, pk: K) -> dict[K, Any]: ...
async def perform_bulk_destroy(self, context: Context, pk: list[K]) -> list[dict[K, Any]]: ...context (a Context instance) is built by route_viewset from settings.viewsets_context_processors - see Architecture.
Operation mixins
CreateMixin [K, T]
POST /→ callsperform_create(context, data: T) -> T
BulkOnlyCreateMixin [K, T]
POST /bulk→ callsperform_bulk_create(context, data: list[T]) -> list[T]
BulkCreateMixin [K, T]
Combines CreateMixin + BulkOnlyCreateMixin.
ListMixin [T, TFilter=None]
GET /→ callsperform_list(context) -> list[T]- Always exposes a
sortquery parameter (column:asc,column:desccomma-separated format). - When
TFilteris provided, filter fields are also exposed as individual query parameters.
Filter hooks:
setup_filter(fltr: TFilter)— pre-filter hook (no-op by default)filter_list(fltr: TFilter, records: list[T]) -> list[T]— post-filter hook (no default; subclasses must implement)
Sort hooks:
setup_sort(sort: SortState)— pre-sort hook (no-op by default)sort_list(sort: SortState, records: list[T]) -> list[T]— post-sort hook (default: stable multi-key in-memory sort; nulls last for asc, nulls first for desc)
RetrieveMixin [K, T]
GET /{pk}→ callsperform_retrieve(context, pk: K) -> T
UpdateMixin [K, T]
PUT /{pk}→ callsperform_update(context, pk, data, partial=False) -> TPATCH /{pk}→ callsperform_update(context, pk, data, partial=True) -> T
BulkOnlyUpdateMixin [K, T]
PUT /bulk→ callsperform_bulk_update(context, records, partial=False) -> list[T]PATCH /bulk→ callsperform_bulk_update(context, records, partial=True) -> list[T]
BulkUpdateMixin [K, T]
Combines UpdateMixin + BulkOnlyUpdateMixin.
DestroyMixin [K, T]
DELETE /{pk}→ callsperform_destroy(context, pk: K) -> dict[K, Any]
BulkOnlyDestroyMixin [K, T]
DELETE /bulk→ callsperform_bulk_destroy(context, pk: list[K]) -> list[dict[K, Any]]
BulkDestroyMixin [K, T]
Combines DestroyMixin + BulkOnlyDestroyMixin.
Sort types
python
class SortDirection(str, Enum):
asc = "asc"
desc = "desc"
class SortStateColumn(BaseModel):
column_name: str # serialises as columnName (camelCase) via model_dump(by_alias=True)
direction: SortDirection = SortDirection.asc
SortState = list[SortStateColumn]parse_sort_param(sort_csv: str | None) -> SortState — parses the sort query string into a SortState. Format: "name:asc,score:desc". Entries with an unknown direction are skipped.
LookupMixin [TLookupFilter=LookupFilter]
GET /lookup→ callsperform_lookup(context) -> list[LookupItem]TLookupFilterdefaults toLookupFilter(singleq: str | Nonefield), so basic title search works without any configuration.- When the filter is active:
setup_lookup_filter(fltr: TLookupFilter)— pre-filter hook (no-op by default)filter_lookup(fltr: TLookupFilter, items: list[LookupItem]) -> list[LookupItem]— post-filter hook; default filters byfltr.q(case-insensitive substring oftitle)
python
class LookupItem(BaseModel):
group: Any
pk: object
title: str
icon: str | None
class LookupFilter(BaseModel):
q: str | None = NoneCombined viewset mixins
ReadOnlyViewSetMixin [K, T]
Inherits: ListMixin[T], RetrieveMixin[K, T]
ViewSetMixin [K, T]
Inherits: CreateMixin, ListMixin, RetrieveMixin, UpdateMixin, DestroyMixin
BulkViewSetMixin [K, T]
Inherits: BulkCreateMixin, ListMixin, RetrieveMixin, BulkUpdateMixin, BulkDestroyMixin
NotFoundError
python
from fastapi_viewsets.response_classes import NotFoundError
raise NotFoundError(pk)
# HTTP 404: {"detail": "Item with pk <pk> not found"}