Skip to content

Generic Views

Repository-backed view classes that implement full CRUD logic automatically. Import from fastapi_views.views.generics.

Generic views follow the repository pattern: you supply a repository object that satisfies the Repository or AsyncRepository protocol, plus schema classes for each operation, and the view wires everything together. Lifecycle hooks (before_create, after_create, …) let you inject custom logic without overriding actions.

Each action calls exactly one repository method:

Action Repository call Class attributes used
list list(*args, **kwargs) or get_filtered_page(filter, **kwargs) response_schema, filter
create create(**data) response_schema, create_schema
retrieve get(*args, **kwargs) response_schema, primary_key
update update_one(values, *args, **kwargs) response_schema, primary_key, update_schema
partial update update_one(values, *args, **kwargs) response_schema, primary_key, partial_update_schema
destroy delete_one(*args, **kwargs) primary_key

get_filtered_page is used whenever filter derives from BasePaginationFilter; it must return an object satisfying the Page protocol (anything exposing items).

The list action's response schema is chosen from filter, and from nothing else: NumberedPage for a PaginationFilter, OffsetPage for an OffsetLimitFilter, CursorPage for a CursorPaginationFilter, and a plain list otherwise. BaseGenericListAPIView defines no response_schema_as_list attribute — that switch belongs to the plain ListAPIView / AsyncListAPIView and is not consulted here. Override get_response_schema(action) if you need a different container.

Override points:

Hook Purpose
get_kwargs(action) Extra criteria merged into every repository call
get_primary_key(primary_key, action) Builds the (args, kwargs) of a detail action
resolve_filter(filter) Turns a non-paginating filter into list() arguments
get_pagination_kwargs() Extra keyword arguments for get_filtered_page
get_fields_key() Where sparse-fieldset projection is applied when serializing
before_create / after_create Around create (likewise for update and partial update)

For a complete walkthrough see Generic views, and sqlargon for ready-made repositories.


AsyncGenericListAPIView

Bases: BaseGenericListAPIView, AsyncListAPIView, WithAsyncRepositoryMixin

AsyncGenericListAPIView

Source code in fastapi_views/views/generics.py
class AsyncGenericListAPIView(
    BaseGenericListAPIView,
    AsyncListAPIView,
    WithAsyncRepositoryMixin,
):
    """AsyncGenericListAPIView"""

    async def list(self, filter: BaseFilter) -> Sequence[M] | Page[M]:
        if type(filter) is _NoFilter:
            return await self.repository.list(**self.get_kwargs())
        self._apply_fields_filter(filter)
        filter.with_kwargs(**self.get_kwargs())
        if isinstance(filter, BasePaginationFilter):
            return await self.repository.get_filtered_page(
                filter, **self.get_pagination_kwargs()
            )
        args, kwargs = self.resolve_filter(filter)
        return await self.repository.list(*args, **kwargs)

GenericListAPIView

Bases: BaseGenericListAPIView, ListAPIView, WithRepositoryMixin

GenericListAPIView

Source code in fastapi_views/views/generics.py
class GenericListAPIView(BaseGenericListAPIView, ListAPIView, WithRepositoryMixin):
    """GenericListAPIView"""

    def list(self, filter: BaseFilter) -> Sequence[M] | Page[M]:
        if type(filter) is _NoFilter:
            return self.repository.list(**self.get_kwargs())
        self._apply_fields_filter(filter)
        filter.with_kwargs(**self.get_kwargs())
        if isinstance(filter, BasePaginationFilter):
            return self.repository.get_filtered_page(
                filter, **self.get_pagination_kwargs()
            )
        args, kwargs = self.resolve_filter(filter)
        return self.repository.list(*args, **kwargs)

AsyncGenericCreateAPIView

Bases: BaseGenericCreateAPIView, AsyncCreateAPIView, WithAsyncRepositoryMixin[M]

AsyncGenericCreateAPIView

Source code in fastapi_views/views/generics.py
class AsyncGenericCreateAPIView(
    BaseGenericCreateAPIView,
    AsyncCreateAPIView,
    WithAsyncRepositoryMixin[M],
):
    """AsyncGenericCreateAPIView"""

    async def create(self, create_schema: BaseModel) -> M | None:
        data = create_schema.model_dump()
        kwargs = self.get_kwargs("create")
        data.update(kwargs)
        await self.before_create(data)
        obj = await self.repository.create(**data)

        if obj is None and self.raise_conflict_create_none:
            self.raise_conflict()
        await self.after_create(obj)
        return obj

    async def before_create(self, data: dict[str, Any]) -> None:
        pass

    async def after_create(self, obj: M | None) -> None:
        pass

GenericCreateAPIView

Bases: BaseGenericCreateAPIView, CreateAPIView, WithRepositoryMixin[M]

GenericCreateAPIView

Source code in fastapi_views/views/generics.py
class GenericCreateAPIView(
    BaseGenericCreateAPIView,
    CreateAPIView,
    WithRepositoryMixin[M],
):
    """GenericCreateAPIView"""

    def create(self, create_schema: BaseModel) -> M | None:
        data = create_schema.model_dump()
        kwargs = self.get_kwargs("create")
        data.update(kwargs)
        self.before_create(data)
        obj = self.repository.create(**data)
        if obj is None and self.raise_conflict_create_none:
            self.raise_conflict()
        self.after_create(obj)
        return obj

    def before_create(self, data: dict[str, Any]) -> None:
        pass

    def after_create(self, obj: M | None) -> None:
        pass

AsyncGenericRetrieveAPIView

Bases: BaseGenericRetrieveAPIView[PK], AsyncRetrieveAPIView, WithAsyncRepositoryMixin[M]

AsyncGenericRetrieveAPIView

Source code in fastapi_views/views/generics.py
class AsyncGenericRetrieveAPIView(
    BaseGenericRetrieveAPIView[PK],
    AsyncRetrieveAPIView,
    WithAsyncRepositoryMixin[M],
):
    """AsyncGenericRetrieveAPIView"""

    async def retrieve(self, pk: PK) -> M | None:
        args, kwargs = self.get_primary_key(pk, action="retrieve")
        return await self.repository.get(*args, **kwargs)

GenericRetrieveAPIView

Bases: BaseGenericRetrieveAPIView[PK], RetrieveAPIView, WithRepositoryMixin[M]

GenericRetrieveAPIView

Source code in fastapi_views/views/generics.py
class GenericRetrieveAPIView(
    BaseGenericRetrieveAPIView[PK],
    RetrieveAPIView,
    WithRepositoryMixin[M],
):
    """GenericRetrieveAPIView"""

    def retrieve(self, pk: PK) -> M | None:
        args, kwargs = self.get_primary_key(pk, action="retrieve")
        return self.repository.get(*args, **kwargs)

AsyncGenericUpdateAPIView

Bases: BaseGenericUpdateAPIView[PK], AsyncUpdateAPIView, WithAsyncRepositoryMixin[M]

AsyncGenericUpdateAPIView

Source code in fastapi_views/views/generics.py
class AsyncGenericUpdateAPIView(
    BaseGenericUpdateAPIView[PK],
    AsyncUpdateAPIView,
    WithAsyncRepositoryMixin[M],
):
    """AsyncGenericUpdateAPIView"""

    async def update(self, pk: PK, update_schema: BaseModel) -> M | None:
        args, kwargs = self.get_primary_key(pk, action="update")
        data = update_schema.model_dump()
        await self.before_update(data)
        obj = await self.repository.update_one(data, *args, **kwargs)
        await self.after_update(obj)
        return obj

    async def before_update(self, data: dict[str, Any]) -> None:
        pass

    async def after_update(self, obj: M | None) -> None:
        pass

GenericUpdateAPIView

Bases: BaseGenericUpdateAPIView[PK], UpdateAPIView, WithRepositoryMixin[M]

GenericUpdateAPIView

Source code in fastapi_views/views/generics.py
class GenericUpdateAPIView(
    BaseGenericUpdateAPIView[PK],
    UpdateAPIView,
    WithRepositoryMixin[M],
):
    """GenericUpdateAPIView"""

    def update(self, pk: PK, update_schema: BaseModel) -> M | None:
        args, kwargs = self.get_primary_key(pk, action="update")
        data = update_schema.model_dump()
        self.before_update(data)
        obj = self.repository.update_one(data, *args, **kwargs)
        self.after_update(obj)
        return obj

    def before_update(self, data: dict[str, Any]) -> None:
        pass

    def after_update(self, obj: M | None) -> None:
        pass

AsyncGenericPartialUpdateAPIView

Bases: BaseGenericPartialUpdateAPIView[PK], AsyncPartialUpdateAPIView, WithAsyncRepositoryMixin[M]

AsyncGenericPartialUpdateAPIView

Source code in fastapi_views/views/generics.py
class AsyncGenericPartialUpdateAPIView(
    BaseGenericPartialUpdateAPIView[PK],
    AsyncPartialUpdateAPIView,
    WithAsyncRepositoryMixin[M],
):
    """AsyncGenericPartialUpdateAPIView"""

    async def partial_update(self, pk: PK, partial_update_schema: BaseModel) -> Any:
        args, kwargs = self.get_primary_key(pk, action="partial_update")
        data = partial_update_schema.model_dump(exclude_unset=True)
        await self.before_partial_update(data)
        obj = await self.repository.update_one(data, *args, **kwargs)
        await self.after_partial_update(obj)
        return obj

    async def before_partial_update(self, data: dict[str, Any]) -> None:
        pass

    async def after_partial_update(self, obj: M | None) -> None:
        pass

GenericPartialUpdateAPIView

Bases: BaseGenericPartialUpdateAPIView[PK], PartialUpdateAPIView, WithRepositoryMixin[M]

GenericPartialUpdateAPIView

Source code in fastapi_views/views/generics.py
class GenericPartialUpdateAPIView(
    BaseGenericPartialUpdateAPIView[PK],
    PartialUpdateAPIView,
    WithRepositoryMixin[M],
):
    """GenericPartialUpdateAPIView"""

    def partial_update(self, pk: PK, partial_update_schema: BaseModel) -> Any:
        args, kwargs = self.get_primary_key(pk, action="partial_update")
        data = partial_update_schema.model_dump(exclude_unset=True)
        self.before_partial_update(data)
        obj = self.repository.update_one(data, *args, **kwargs)
        self.after_partial_update(obj)
        return obj

    def before_partial_update(self, data: dict[str, Any]) -> None:
        pass

    def after_partial_update(self, obj: M | None) -> None:
        pass

AsyncGenericDestroyAPIView

Bases: BaseGenericDestroyAPIView[PK], AsyncDestroyAPIView, WithAsyncRepositoryMixin

AsyncGenericDestroyAPIView

Source code in fastapi_views/views/generics.py
class AsyncGenericDestroyAPIView(
    BaseGenericDestroyAPIView[PK],
    AsyncDestroyAPIView,
    WithAsyncRepositoryMixin,
):
    """AsyncGenericDestroyAPIView"""

    async def destroy(self, pk: PK) -> Any:
        args, kwargs = self.get_primary_key(pk, action="destroy")
        await self.repository.delete_one(*args, **kwargs)

GenericDestroyAPIView

Bases: BaseGenericDestroyAPIView[PK], DestroyAPIView, WithRepositoryMixin

GenericDestroyAPIView

Source code in fastapi_views/views/generics.py
class GenericDestroyAPIView(
    BaseGenericDestroyAPIView[PK],
    DestroyAPIView,
    WithRepositoryMixin,
):
    """GenericDestroyAPIView"""

    def destroy(self, pk: PK) -> Any:
        args, kwargs = self.get_primary_key(pk, action="destroy")
        self.repository.delete_one(*args, **kwargs)

AsyncGenericViewSet

Bases: AsyncGenericListAPIView, AsyncGenericRetrieveAPIView, AsyncGenericCreateAPIView, AsyncGenericUpdateAPIView, AsyncGenericPartialUpdateAPIView, AsyncGenericDestroyAPIView

AsyncGenericViewSet

Source code in fastapi_views/views/generics.py
class AsyncGenericViewSet(
    AsyncGenericListAPIView,
    AsyncGenericRetrieveAPIView,
    AsyncGenericCreateAPIView,
    AsyncGenericUpdateAPIView,
    AsyncGenericPartialUpdateAPIView,
    AsyncGenericDestroyAPIView,
):
    """AsyncGenericViewSet"""

GenericViewSet

Bases: GenericListAPIView, GenericRetrieveAPIView, GenericCreateAPIView, GenericUpdateAPIView, GenericPartialUpdateAPIView, GenericDestroyAPIView

GenericViewSet

Source code in fastapi_views/views/generics.py
class GenericViewSet(
    GenericListAPIView,
    GenericRetrieveAPIView,
    GenericCreateAPIView,
    GenericUpdateAPIView,
    GenericPartialUpdateAPIView,
    GenericDestroyAPIView,
):
    """GenericViewSet"""