FastCRUD 0.19.2
Warning
Deprecated Behavior - Action Required for Next Major Version
The create() method will change its behavior in v0.20.0 for consistency with other CRUD methods. Current usage patterns will show deprecation warnings:
# ⚠️ Will return None instead of SQLAlchemy model in v0.20.0
user = await user_crud.create(db=db, object=user_data)
# Warning: create() without schema_to_select will return None instead of the SQLAlchemy model
# ⚠️ Will properly respect schema_to_select plus return_as_model=False parameter in v0.20.0
user = await user_crud.create(db=db, object=user_data, schema_to_select=UserRead)
# Warning: create() with schema_to_select and return_as_model=False will default to returning dict
# ✅ Future-compatible usage (works now and in v0.20.0)
user_dict = await user_crud.create(
db=db,
object=user_data,
schema_to_select=UserRead,
return_as_model=False # Explicit: returns dict
)
user_model = await user_crud.create(
db=db,
object=user_data,
schema_to_select=UserRead,
return_as_model=True # Explicit: returns Pydantic model
)Added
- get_joined Method Overloads by @igorbenav
- Added missing
@overloadsignatures forget_joined()method to support proper type inference - Added
return_as_modelparameter for converting joined results to Pydantic models - Enhanced type safety: returns
SelectSchemaTypewhenreturn_as_model=True,dictwhenFalse - Consistent API with other CRUD methods like
get(),update(), etc.
- Added missing
Improved
- create Method Performance and Consistency by @igorbenav
- Removed unnecessary database round-trip by eliminating redundant
get()call after creation - Added deprecation warnings for upcoming API consistency changes in next major version
- Fixed type hints to match actual implementation behavior (removed incorrect
Nonereturn type)
- Removed unnecessary database round-trip by eliminating redundant
Deprecated
- create Method Behavior Changes (Warnings Added)
create()withoutschema_to_selectwill returnNoneinstead of SQLAlchemy model in next major versioncreate()withschema_to_selectwill properly respectreturn_as_modelparameter in next major version- These changes align
create()behavior withupdate()and other CRUD methods for consistency
Fixed
- Type Safety Issues by @igorbenav
- Fixed
get_joined()method type annotations to properly reflect actual return types - Corrected
create()method type hints to remove impossibleNonereturn type - Enhanced test coverage with 8 new comprehensive tests for
get_joinedreturn type variations
- Fixed
Breaking Changes
Details
get_joined Method Overloads and return_as_model Parameter
Problem Solved
The get_joined() method was missing proper type overloads and the return_as_model parameter, creating inconsistency with other CRUD methods:
# Before: No return_as_model parameter, unclear return types
result = await user_crud.get_joined(
db=db,
join_model=Tier,
join_prefix="tier_",
schema_to_select=UserWithTier
)
# Type: dict[str, Any] - always dict, no model optionSolution Implemented
Added complete overload signatures and return_as_model parameter to match other CRUD methods:
# After: Clear return types based on parameters
user_dict = await user_crud.get_joined(
db=db,
join_model=Tier,
join_prefix="tier_",
schema_to_select=UserWithTier,
return_as_model=False # Default: dict
)
# Type: Optional[dict[str, Any]]
user_model = await user_crud.get_joined(
db=db,
join_model=Tier,
join_prefix="tier_",
schema_to_select=UserWithTier,
return_as_model=True # Pydantic model
)
# Type: Optional[UserWithTier]New Overload Pattern
@overload
async def get_joined(
self,
db: AsyncSession,
*,
schema_to_select: type[SelectSchemaType],
return_as_model: Literal[True],
**kwargs: Any,
) -> Optional[SelectSchemaType]: ...
@overload
async def get_joined(
self,
db: AsyncSession,
*,
schema_to_select: type[SelectSchemaType],
return_as_model: Literal[False] = False,
**kwargs: Any,
) -> Optional[dict[str, Any]]: ...Benefits
- API Consistency:
get_joined()now matchesget(),update(), and other methods - Type Safety: Precise return types based on
return_as_modelparameter - Flexibility: Choose between dict access or Pydantic model validation
- Enhanced IDE Support: Better autocomplete and type checking
create Method Performance and Consistency Improvements
Problem Solved
The create() method had several inconsistencies compared to other CRUD methods:
- Performance Issue: Unnecessary database round-trip when using
schema_to_select - Inconsistent Behavior: Didn't behave like
update()and other methods - Type Confusion: Return types didn't match actual implementation
# Before: Inconsistent behavior
user = await user_crud.create(db=db, object=user_data)
# Returns: SQLAlchemy model (different from update())
user = await user_crud.create(
db=db,
object=user_data,
schema_to_select=UserRead
)
# Triggers unnecessary get() call after creationSolution Implemented
- Eliminated Redundant Database Query: Removed unnecessary
get()call after creation - Added Deprecation Warnings: Clear migration path for next major version
- Fixed Type Hints: Accurate types matching current implementation
# Current behavior with deprecation warnings
user = await user_crud.create(db=db, object=user_data)
# Warning: Will return None instead of SQLAlchemy model in next major version
user = await user_crud.create(
db=db,
object=user_data,
schema_to_select=UserRead,
return_as_model=True
)
# No extra DB query, direct conversion to Pydantic modelPerformance Impact
Before: create() with schema_to_select = 2 database operations
INSERTstatement to create recordSELECTstatement viaget()call to fetch created data
After: create() with schema_to_select = 1 database operation
INSERTstatement with direct result conversion
Deprecation Migration Guide
Current v0.19.2 (with warnings):
# Case 1: No schema_to_select (shows warning)
user = await crud.create(db=db, object=user_data)
# Returns: SQLAlchemy model
# Warning: Will return None in next major version
# Case 2: With schema_to_select (shows warning if no explicit return_as_model)
user = await crud.create(db=db, object=user_data, schema_to_select=UserRead)
# Returns: dict (default return_as_model=False)
# Warning: Behavior will be consistent in next major versionFuture v0.20.0:
# Case 1: No schema_to_select
user = await crud.create(db=db, object=user_data)
# Returns: None (like update() method)
# Case 2: With schema_to_select
user_dict = await crud.create(
db=db,
object=user_data,
schema_to_select=UserRead,
return_as_model=False
)
# Returns: dict
user_model = await crud.create(
db=db,
object=user_data,
schema_to_select=UserRead,
return_as_model=True
)
# Returns: Pydantic modelBenefits
- Performance: Up to 50% faster creation with
schema_to_select - Consistency: Matches behavior of
update()and other CRUD methods - Type Safety: Clear, predictable return types
- Migration Path: Deprecation warnings guide users to new patterns
Enhanced Test Coverage
Added 8 comprehensive tests covering all get_joined return type scenarios:
- SQLAlchemy tests: 4 new test cases
- SQLModel tests: 4 new test cases
- Coverage: All combinations of
return_as_modelparameter usage - Validation: Proper type checking and error handling
What's Changed
- get version dynamically by @igorbenav in #287
- Some bug fixes by @igorbenav in #289
- change version by @igorbenav in #290
Full Changelog: v0.19.1...v0.19.2