Release 1.3.0
May 10, 2026 · View on GitHub
This release introduces a Django-like way to eliminate N+1 queries: an inner
RelatedConfig class on Pydantic schemas that tells the ORM adapter which
relationships to eager-load on LIST and GET endpoints.
Highlights
Declarative eager loading via RelatedConfig
- Add
select_related = [...](FK / many-to-one) and/orprefetch_related = [...](collections / many-to-many) to a Pydantic schema's innerRelatedConfigclass. - When the schema is used as
response_modelin a viewset,BaseViewsetandAsyncBaseViewsetautomatically forward these lists to the ORM adapter so relationships are loaded in a single (or minimal) round-trip. - No changes in the viewset itself are required — configuration lives in the schema, next to the fields it describes.
Example:
class PostSchema(BaseModel):
model_config = ConfigDict(from_attributes=True)
id: int
title: str
author: AuthorSchema # nested → needs join
class RelatedConfig:
select_related = ["author"] # SQLAlchemy: joinedload
prefetch_related = ["tags"] # SQLAlchemy: selectinload
posts = AsyncBaseViewset(
endpoint="/posts",
model=Post,
response_model=PostSchema,
db_session=get_async_session,
)
Adapter-level support
| ORM | select_related | prefetch_related | Implementation |
|---|---|---|---|
| SQLAlchemy (sync) | ✅ | ✅ | joinedload / selectinload on Query |
| SQLAlchemy (async) | ✅ | ✅ | joinedload / selectinload on select() + result.unique() |
| Tortoise ORM | ✅* | ✅ | prefetch_related() for both (*Tortoise has no separate select_related) |
| Peewee | ✅ | — | .join() for select_related |
- All adapter methods (
get_list_queryset,get_list_queryset_async,get_element_by_id,get_element_by_id_async) accept optionalselect_relatedandprefetch_relatedkeyword arguments for explicit overrides. - The low-level utilities in
fastapi_viewsets.utilsandfastapi_viewsets.async_utilsalso accept these arguments, plus an optionalresponse_model. Whenresponse_modelis provided and the explicit lists are omitted, the utilities read them automatically fromRelatedConfig.
Backward compatibility
- Every new parameter defaults to
None. Existing code, tests and subclassed viewsets continue to work without any changes. - The public API surface of
BaseViewsetandAsyncBaseViewsetis unchanged; only the internal calls to the ORM adapters now forward additional optional kwargs.
Internal additions
fastapi_viewsets.serializer_utils— small helper module that extractsselect_relatedandprefetch_relatedfrom a Pydantic model'sRelatedConfiginner class.
Tests
- 258+ tests pass (219 new/legacy + 39 skipped for optional ORMs).
- Coverage remains above the 70% gate.
- New dedicated test file:
tests/test_select_prefetch_related.pycoveringserializer_utils, SQLAlchemy sync/async adapters, and the integration betweenutils/async_utilswithRelatedConfig.
Upgrade
pip install -U fastapi-viewsets==1.3.0
No code changes are required for existing users. To opt into eager loading,
add a RelatedConfig class to the Pydantic schemas you already pass as
response_model.