Customization
Every collection is configured in one of two interchangeable ways, and its behaviour is tuned by overriding methods on a subclass. This page is the reference for both. For task-oriented, copy-paste examples see the Cookbook — every recipe there is backed by a test.
Two ways to configure
A setting can be passed to the constructor or declared as a class attribute. They are equivalent; the constructor argument wins when both are given.
# constructor
crud = CRUDCollection(orm_adapter=adapter, disable_delete=True)
# class attribute — handy when several collections share config
class ArticleCRUD(CRUDCollection):
orm_adapter = adapter
disable_delete = True
Class attributes compose through normal inheritance:
class AuthenticatedCRUD(CRUDCollection):
dependencies = [Depends(require_auth)]
class ArticleCRUD(AuthenticatedCRUD):
orm_adapter = SQLModelAdapter(model=Article, get_session=get_session)
Options reference
Adapter & primary key
| Option | Type | Default | Purpose |
|---|---|---|---|
orm_adapter |
ORMAdapterBase |
— (required) | The ORM adapter all data access goes through. |
pk_fields |
type[BaseModel] |
derived from adapter | Model of primary-key fields; drives the /{...} path params. |
Schemas
Leave these unset to have them generated from the model; set one to take full control of that shape.
| Option | Type | Default |
|---|---|---|
public_schema |
BaseModel |
adapter.generate_public_schema(...) |
public_list_schema |
BaseModel |
PaginatorPage[public_schema] |
create_schema |
BaseModel |
generated (lazily, see note) |
update_schema |
BaseModel |
generated, all fields optional |
filter_schema |
BaseModel |
one optional query field per scalar |
sort_schema |
BaseModel |
?sort=field:asc\|desc values |
include_schema |
BaseModel |
one entry per relation |
create_out_schema / update_out_schema |
any | response_model for POST / PATCH |
create_schema is resolved lazily
Unlike the others, the create schema is finalised when the router is
built, because a nested collection's strategy may drop the parent's
foreign key from it. self.create_schema is therefore None on the
instance — don't construct it directly inside a hook.
Field selection
Instead of writing a whole schema, restrict which model fields feed the generated ones:
| Option | Applies to |
|---|---|
base_fields |
fallback for all generated schemas |
public_fields |
the public (GET) schema |
create_fields |
the create (POST) schema |
update_fields |
the update (PATCH) schema |
The same sets can live on the model itself as a crud_config — see
Schema Generation.
Disabling endpoints
Each flag drops one route. None (the constructor default) means
"inherit the class attribute"; True/False set it outright.
| Option | Removes |
|---|---|
disable_get_many |
GET / |
disable_get_one |
GET /{pk} |
disable_create |
POST / |
disable_update |
PATCH /{pk} |
disable_delete |
DELETE /{pk} |
Dependencies
| Option | Scope |
|---|---|
dependencies |
all routes of the collection |
get_one_dependencies |
GET /{pk} only |
get_many_dependencies |
GET / only |
create_dependencies |
POST / only |
update_dependencies |
PATCH /{pk} only |
delete_dependencies |
DELETE /{pk} only |
Pass collection-wide deps via dependencies, not router_kwargs
A dependencies= value smuggled through **router_kwargs is
overwritten by self.dependencies when the router is built. Use the
dependencies option.
Other
| Option | Type | Purpose |
|---|---|---|
dependency_overrides |
dict[type, ...] |
Replace a dependency marker (see below). |
**router_kwargs |
— | Forwarded to APIRouter(**...) (tags, prefix, etc.). |
Overridable methods
Subclass CRUDCollection and override what you need. Signatures below
are exact — match them.
get_id_path
Returns the single-object path segment (default /{article_id}, built
from pk_fields). exclude drops params an ancestor already placed in
the path. Override it to pin a fixed segment for a token-scoped
singleton whose identity comes from auth rather than the URL:
See the /users/me recipe.
get_one_not_found
Called by GET /{pk} when the row is missing; the default raises
HTTPException(404). This is the only formal not-found hook — for
create/update/delete the 404 is raised inside the handler itself.
Override it to return a fallback, or to create-on-first-access.
Route handlers
async def get_one_handler(self, pk_field_values, include_data, parent_refs)
async def get_many_handler(self, paginator, filter_data, sort_data, include_data, parent_refs)
async def create_one_handler(self, create_data, parent_refs)
async def update_one_handler(self, pk_field_values, update_data, parent_refs)
async def delete_one_handler(self, pk_field_values, parent_refs)
Override a handler to pre- or post-process around the adapter call.
Keep the marker annotations
Each handler parameter is annotated Annotated[..., XDependency].
Those markers are what the router rewrites into real request params.
An override with plain, unannotated parameters makes them leak into
the query string and the request fails with 422. Copy the annotations
verbatim — see the handler recipe.
apply_pk_aliases and generate_unique_id
def apply_pk_aliases(self, pk_schema: type[BaseModel]) -> type[BaseModel]
def generate_unique_id(self, route: APIRoute) -> str
apply_pk_aliases adds the {model}_id alias to bare PK fields (so id
becomes {article_id} in the path); override to change that naming.
generate_unique_id builds the OpenAPI operationId.
Replacing a dependency with dependency_overrides
Handlers declare their inputs as marker classes from
fastapi_crud_generator.deps (e.g. PKFieldsDependency,
CreateSchemaDependency). dependency_overrides swaps the
implementation behind a marker — the key is the marker class, the value
is either a ReplaceSignatureDependency or a raw annotation (which is
wrapped automatically).
The canonical use is replacing the primary key with a value from auth,
so /{pk} becomes token-scoped:
class UserMeCRUD(CRUDCollection):
dependency_overrides = {
PKFieldsDependency: Annotated[UserPK, Depends(get_current_user)],
}
Markers you can override: CreateSchemaDependency,
UpdateSchemaDependency, PublicSchemaDependency,
PublicListSchemaDependency, FilterSchemaDependency,
SortSchemaDependency, IncludeSchemaDependency, PKFieldsDependency,
PaginatorDependency, ParentPKFieldsDependency.