- Declarative eager loading via
RelatedConfiginside Pydantic schemas.
Addselect_related = [...]and/orprefetch_related = [...]to a schema's innerRelatedConfigclass, andBaseViewset/AsyncBaseViewsetautomatically appliesjoinedload/selectinload(SQLAlchemy) orprefetch_related(Tortoise) onLISTandGETendpoints. This eliminates N+1 queries without duplicating configuration between schemas and viewsets. - Adapter-level support for
select_relatedandprefetch_relatedacross all built-in ORM adapters (SQLAlchemy sync/async, Tortoise, Peewee). - Low-level utility integration:
get_list_queryset,get_element_by_id, and their async counterparts acceptresponse_model,select_related, andprefetch_related. Whenresponse_modelis provided and explicit lists are omitted, the utilities read them automatically fromRelatedConfig. - Full backward compatibility: all new parameters default to
None; existing code and tests work unchanged.
- New dedicated test suite:
tests/test_select_prefetch_related.pycoveringserializer_utils, SQLAlchemy sync/async adapters, and utility integration. - 258+ tests pass, coverage above the 70% gate.
Details: RELEASE_1.3.0.md.
SQLAlchemyAdapterno longer crashes at construction when the async DB-API driver (aiosqlite/asyncpg/aiomysql) is missing. Sync-only setups keep working out of the box;get_async_session()raises a helpfulRuntimeErrorlazily if you try to use async without the driver. Regression introduced in 1.2.0 by always passing an explicitasync_database_urlfromORMFactory.get_adapter_from_env.
- Switched to
[tool.setuptools.packages.find]so future subpackages are picked up automatically by wheel/sdist builds.
- Pydantic v2 first. CRUD handlers serialize bodies with
model_dump(exclude_unset=...), fixing PATCH semantics so unset fields are no longer overwritten with defaults. - Lazy
db_conf. Importingfastapi_viewsetsno longer creates SQLAlchemy engines unless they are accessed, and no longer fails when an async driver such asaiosqliteis missing. - Single source of truth for sync→async URL conversion
(
to_async_database_url) and for the default ORM adapter singleton (ORMFactory.get_default_adapter). - Internal refactor.
BaseViewset.registerandAsyncBaseViewset.registerwere deduplicated into a shared_RegisterMixin. Bareexcept: passblocks were replaced with narrow guards. The no-op auth dependencybutlewas renamed to_noop_dependency(the old name remains as an alias).
- Added PEP 621
pyproject.tomland trimmedsetup.pyto a shim. python_requires>=3.9,pydantic>=2.5,<3,fastapi>=0.110.- Pre-configured
[tool.ruff],[tool.black],[tool.mypy], plus alintextra that pulls in ruff/black/mypy.
- The
butleno-op dependency name still works. - Pydantic v1 schemas keep working via a transparent fallback in
fastapi_viewsets._compat.model_to_dict, but the test matrix now targets Pydantic v2. BaseViewset/AsyncBaseViewsetpublic APIs are unchanged.
Details: RELEASE_1.2.0.md.
This major release introduces multi-ORM support, allowing you to choose between SQLAlchemy, Tortoise ORM, and Peewee. The library now uses an adapter pattern to provide a unified interface for different ORM implementations, making it more flexible and extensible.
- Multi-ORM Support: Choose your preferred ORM - SQLAlchemy (default), Tortoise ORM, or Peewee
- ORM Adapter Pattern: Unified interface for all ORM operations through
BaseORMAdapter - ORMFactory: Factory class for creating and managing ORM adapters based on configuration
- Environment-based Configuration: Configure your ORM choice through environment variables (
ORM_TYPE) - Flexible Database Configuration: Support for different database URLs per ORM type
- Backward Compatibility: Existing SQLAlchemy code continues to work without changes
- Modular Architecture: Clean separation of ORM-specific logic into adapters
- Better Code Organization: ORM adapters are now in a dedicated
ormpackage - Enhanced Configuration: Support for ORM-specific configuration through environment variables
- Improved Error Handling: Better error messages for missing ORM dependencies
- Code Quality: Improved code structure and maintainability
- FastAPI >= 0.76.0
- SQLAlchemy >= 1.4.36 (default, core dependency)
- Python >= 3.6
Optional Dependencies:
tortoise-orm>=0.20.0andasyncpg>=0.28.0for Tortoise ORM supportpeewee>=3.17.0for Peewee ORM support
- Comprehensive test suite with 200+ tests
- 70%+ code coverage
- Unit tests for all ORM adapters
- Integration tests for each ORM
- Edge case and error handling tests
- Both sync and async test coverage
- Updated README with multi-ORM configuration examples
- Added ORM adapter documentation
- Configuration examples for each supported ORM
- Migration guide for existing users
If you're upgrading from version 1.0.1:
-
No Breaking Changes: Existing code using SQLAlchemy will continue to work without modifications. SQLAlchemy remains the default ORM.
-
Using a Different ORM: To use Tortoise or Peewee, set the
ORM_TYPEenvironment variable:# For Tortoise ORM export ORM_TYPE=tortoise export DATABASE_URL=postgresql://user:pass@localhost/db export TORTOISE_MODELS=["app.models"] # For Peewee ORM export ORM_TYPE=peewee export DATABASE_URL=sqlite:///database.db
-
Custom Adapter: You can now pass a custom
orm_adapterto viewsets:from fastapi_viewsets.orm.factory import ORMFactory adapter = ORMFactory.create_adapter('sqlalchemy', { 'database_url': 'postgresql://...' }) viewset = BaseViewset( model=User, orm_adapter=adapter, ... )
The library now supports three ORM adapters:
-
SQLAlchemyAdapter (default)
- Full sync and async support
- Works with all SQLAlchemy-compatible databases
-
TortoiseAdapter
- Async-only ORM
- Perfect for high-performance async applications
- Requires
tortoise-ormand async database drivers
-
PeeweeAdapter
- Sync-only ORM
- Lightweight and simple
- Requires
peewee
Configure your ORM through environment variables in .env:
# Choose your ORM
ORM_TYPE=sqlalchemy # or 'tortoise' or 'peewee'
# Database URL (used by all ORMs)
DATABASE_URL=postgresql://user:pass@localhost/db
# SQLAlchemy-specific
SQLALCHEMY_DATABASE_URL=postgresql://user:pass@localhost/db
SQLALCHEMY_ASYNC_DATABASE_URL=postgresql+asyncpg://user:pass@localhost/db
# Tortoise-specific
TORTOISE_DATABASE_URL=postgresql://user:pass@localhost/db
TORTOISE_MODELS=["app.models", "app.other"]
TORTOISE_APP_LABEL=models
# Peewee-specific
PEEWEE_DATABASE_URL=sqlite:///database.dbThank you to all contributors and users who provided feedback and reported issues!
This release brings significant improvements to the FastAPI ViewSets library, making it more robust, feature-rich, and production-ready.
- Full Async Support: Complete async/await support with
AsyncBaseViewsetfor high-performance applications - Comprehensive Type Hints: Full type annotation support throughout the codebase for better IDE experience and code maintainability
- Improved Error Handling: Enhanced error handling with specific exceptions for integrity errors and database errors
- PUT vs PATCH Support: Proper distinction between PUT (full replacement) and PATCH (partial update) operations
- Route Registration Improvements: Fixed route registration order to properly handle LIST and GET endpoints
- Fixed 405 Method Not Allowed error for LIST endpoints
- Fixed database session leaks by ensuring proper session cleanup
- Fixed PUT/PATCH update logic to correctly handle partial updates
- Fixed limit=0 handling to return empty list instead of all items
- Fixed primary key exclusion in PUT updates
- Improved validation for required fields during creation
- Better Database Session Management: Proper try/finally blocks to ensure sessions are always closed
- Enhanced Route Registration: Improved order of route registration to prevent conflicts between LIST and GET endpoints
- Code Quality: Removed unused code, improved code structure and organization
- Documentation: Updated README with comprehensive examples and API descriptions
- FastAPI >= 0.76.0
- SQLAlchemy >= 1.4.36
- Python >= 3.6
- Comprehensive test suite with 108+ tests
- 86% code coverage
- Unit tests for all core components
- Integration tests for full CRUD workflows
- Edge case testing
- Both sync and async test coverage
- Updated README with async examples
- Improved code examples
- Better API documentation
- Clear distinction between sync and async usage
If you're upgrading from a previous version:
-
Async Support: If you want to use async features, install an async database driver:
pip install aiosqlite # for SQLite # or pip install asyncpg # for PostgreSQL
-
PUT/PATCH: PUT now performs full replacement (sets missing fields to None), while PATCH only updates provided fields. Make sure your Pydantic schemas support optional fields for PATCH operations.
-
Route Registration: The library now automatically handles route registration order. No changes needed in your code.
Thank you to all contributors and users who provided feedback and reported issues!
pip install fastapi-viewsetsFor async support:
pip install fastapi-viewsets aiosqlitefrom fastapi import FastAPI
from fastapi_viewsets import BaseViewset
from fastapi_viewsets.db_conf import Base, get_session, engine
app = FastAPI()
# Define your model and schema
# ... (see README for full example)
# Create viewset
user_viewset = BaseViewset(
endpoint='/users',
model=User,
response_model=UserSchema,
db_session=get_session,
tags=['Users']
)
# Register endpoints
user_viewset.register()
# Include in app
app.include_router(user_viewset)