Fastcrud

Latest version: v0.13.0

Safety actively analyzes 638297 Python packages for vulnerabilities to keep your Python projects secure.

Scan your dependencies

Page 1 of 3

0.13.0

Added
- Filters in Automatic Endpoints 🎉
- One-to-many support in joins
- Upsert method in FastCRUD class by dubusster

Detailed Changes
Using Filters in FastCRUD

FastCRUD provides filtering capabilities, allowing you to filter query results based on various conditions. Filters can be applied to `read_multi` and `read_paginated` endpoints. This section explains how to configure and use filters in FastCRUD.


Defining Filters

Filters are either defined using the `FilterConfig` class or just passed as a dictionary. This class allows you to specify default filter values and validate filter types. Here's an example of how to define filters for a model:

python
from fastcrud import FilterConfig

Define filter configuration for a model
filter_config = FilterConfig(
tier_id=None, Default filter value for tier_id
name=None Default filter value for name
)


And the same thing using a `dict`:
python
filter_config = {
"tier_id": None, Default filter value for tier_id
"name": None, Default filter value for name
}


By using `FilterConfig` you get better error messages.

Applying Filters to Endpoints

You can apply filters to your endpoints by passing the `filter_config` to the `crud_router` or `EndpointCreator`. Here's an example:

python
from fastcrud import crud_router
from yourapp.models import YourModel
from yourapp.schemas import CreateYourModelSchema, UpdateYourModelSchema
from yourapp.database import async_session

Apply filters using crud_router
app.include_router(
crud_router(
session=async_session,
model=YourModel,
create_schema=CreateYourModelSchema,
update_schema=UpdateYourModelSchema,
filter_config=filter_config, Apply the filter configuration
path="/yourmodel",
tags=["YourModel"]
)
)


Using Filters in Requests

Once filters are configured, you can use them in your API requests. Filters are passed as query parameters. Here's an example of how to use filters in a request to a paginated endpoint:

http
GET /yourmodel/get_paginated?page=1&itemsPerPage=3&tier_id=1&name=Alice


Custom Filter Validation

The `FilterConfig` class includes a validator to check filter types. If an invalid filter type is provided, a `ValueError` is raised. You can customize the validation logic by extending the `FilterConfig` class:

python
from fastcrud import FilterConfig
from pydantic import ValidationError

class CustomFilterConfig(FilterConfig):
field_validator("filters")
def check_filter_types(cls, filters: dict[str, Any]) -> dict[str, Any]:
for key, value in filters.items():
if not isinstance(value, (type(None), str, int, float, bool)):
raise ValueError(f"Invalid default value for '{key}': {value}")
return filters

try:
Example of invalid filter configuration
invalid_filter_config = CustomFilterConfig(invalid_field=[])
except ValidationError as e:
print(e)


Handling Invalid Filter Columns

FastCRUD ensures that filters are applied only to valid columns in your model. If an invalid filter column is specified, a `ValueError` is raised:

python
try:
Example of invalid filter column
invalid_filter_config = FilterConfig(non_existent_column=None)
except ValueError as e:
print(e) Output: Invalid filter column 'non_existent_column': not found in model


___
Handling One-to-One and One-to-Many Joins in FastCRUD

FastCRUD provides flexibility in handling one-to-one and one-to-many relationships through `get_joined` and `get_multi_joined` methods, along with the ability to specify how joined data should be structured using both the `relationship_type` (default `one-to-one`) and the `nest_joins` (default `False`) parameters.

One-to-One Relationships
- **`get_joined`**: Fetch a single record and its directly associated record (e.g., a user and their profile).
- **`get_multi_joined`** (with `nest_joins=False`): Retrieve multiple records, each linked to a single related record from another table (e.g., users and their profiles).


**Example**

Let's define two tables:

python
class User(Base):
__tablename__ = "user"
id = Column(Integer, primary_key=True)
name = Column(String)
tier_id = Column(Integer, ForeignKey("tier.id"))

class Tier(Base):
__tablename__ = "tier"
id = Column(Integer, primary_key=True)
name = Column(String, unique=True)


Fetch a user and their tier:

python
user_tier = await user_crud.get_joined(
db=db,
join_model=Tier,
join_on=User.tier_id == Tier.id,
join_type="left",
join_prefix="tier_",
id=1
)


The result will be:

json
{
"id": 1,
"name": "Example",
"tier_id": 1,
"tier_name": "Free"
}


**One-to-One Relationship with Nested Joins**

To get the joined data in a nested dictionary:

python
user_tier = await user_crud.get_joined(
db=db,
join_model=Tier,
join_on=User.tier_id == Tier.id,
join_type="left",
join_prefix="tier_",
nest_joins=True,
id=1
)


The result will be:

json
{
"id": 1,
"name": "Example",
"tier": {
"id": 1,
"name": "Free"
}
}



One-to-Many Relationships
- **`get_joined`** (with `nest_joins=True`): Retrieve a single record with all its related records nested within it (e.g., a user and all their blog posts).
- **`get_multi_joined`** (with `nest_joins=True`): Fetch multiple primary records, each with their related records nested (e.g., multiple users and all their blog posts).

> [!WARNING]
> When using `nest_joins=True`, the performance will always be a bit worse than when using `nest_joins=False`. For cases where more performance is necessary, consider using `nest_joins=False` and remodeling your database.


**Example**

To demonstrate a one-to-many relationship, let's assume `User` and `Post` tables:

python
class User(Base):
__tablename__ = "user"
id = Column(Integer, primary key=True)
name = Column(String)

class Post(Base):
__tablename__ = "post"
id = Column(Integer, primary key=True)
user_id = Column(Integer, ForeignKey("user.id"))
content = Column(String)


Fetch a user and all their posts:

python
user_posts = await user_crud.get_joined(
db=db,
join_model=Post,
join_on=User.id == Post.user_id,
join_type="left",
join_prefix="post_",
nest_joins=True,
id=1
)


The result will be:

json
{
"id": 1,
"name": "Example User",
"posts": [
{
"id": 101,
"user_id": 1,
"content": "First post content"
},
{
"id": 102,
"user_id": 1,
"content": "Second post content"
}
]
}



What's Changed
- feat: ✨ add upsert method in FastCRUD class by [dubusster](https://github.com/dubusster)
- Filters in Automatic Endpoints
- One-to-many support in joins
- tests fixed by igorbenav
- Using the same session for all tests
- warning added to docs


**Full Changelog**: https://github.com/igorbenav/fastcrud/compare/v0.12.1...v0.13.0

0.12.1

Added
- Deprecation Warning for dependency handling.

Detailed Changes
If you pass a sequence of `params.Depends` type variables to any `*_deps` parameter in `EndpointCreator` and `crud_router`, you'll get a warning. Support will be completely removed in 0.15.0.

**Full Changelog**: https://github.com/igorbenav/fastcrud/compare/v0.12.0...v0.12.1

0.12.0

Added
- Unpaginated versions of multi-row get methods by slaarti in 62 🎉
- Nested Join bug fixes
- Dependency handling now working as docs say
- Option to Skip commit in some fastcrud methods
- Docstring example fixes
- `__in` and `__not_in` filters by JakNowy 🎉
- Fastapi 0.111.0 support

Detailed Changes
Unpaginated versions of multi-row get methods
Now, if you pass `None` to `limit` in `get_multi` and `get_multi_joined`, you get the whole unpaginated set of data that matches the filters. Use this with caution.

python
from fastcrud import FastCRUD
from .models.item import Item
from .database import session as db

crud_items = FastCRUD(Item)
items = await crud_items.get_multi(db=db, limit=None)
this will return all items in the db


Dependency handling now working as docs say
Now, you may pass dependencies to `crud_router` or `EndpointCreator` as simple functions instead of needing to wrap them in `fastapi.Depends`.

python
from .dependencies import get_superuser
app.include_router(
crud_router(
session=db,
model=Item,
create_schema=ItemCreate,
update_schema=ItemUpdate,
delete_schema=ItemDelete,
create_deps=[get_superuser],
update_deps=[get_superuser],
delete_deps=[get_superuser],
path="/item",
tags=["item"],
)
)


Option to Skip commit in some fastcrud methods
For `create`, `update`, `db_delete` and `delete` methods of `FastCRUD`, now you have the option of passing `commit=False` so you don't commit the operations immediately.

python
from fastcrud import FastCRUD
from .models.item import Item
from .database import session as db

crud_items = FastCRUD(Item)

await crud_items.delete(
db=db,
commit=False,
id=1
)
this will not actually delete until you run a db.commit()


`__in` and `__not_in` filters
You may now pass `__in` and `__not_in` to methods that accept advanced queries:

- `__gt`: greater than,
- `__lt`: less than,
- `__gte`: greater than or equal to,
- `__lte`: less than or equal to,
- `__ne`: not equal,
- `__in`: included in [tuple, list or set],
- `__not_in`: not included in [tuple, list or set].

What's Changed
- Add unpaginated versions of multi-row get methods (w/tests) by [slaarti](https://github.com/slaarti) 🎉
- Join fixes
- Dependencies
- Skip commit
- Docstring fix
- feat: filter __in by [JakNowy](https://github.com/JakNowy) 🎉
- python support for 0.111.0 added
- version bump in pyproject.toml for 0.12.0

New Contributors
* [slaarti](https://github.com/slaarti) made their first contribution in https://github.com/igorbenav/fastcrud/pull/62 🎉

**Full Changelog**: https://github.com/igorbenav/fastcrud/compare/v0.11.1...v0.12.0

0.11.1

Added
- `one_or_none` parameter to FastCRUD `get` method (default `False`)
- `nest_joins` parameter to FastCRUD `get_joined` and `get_multi_joined` (default `False`)

Detailed Changes
`get`
By default, the `get` method in `FastCRUD` returns the `first` object matching all the filters it finds.

If you want to ensure the `one_or_none` behavior, you may pass the parameter as `True`:

python
crud.get(
async_session,
one_or_none=True,
category_id=1
)


`get_joined` and `get_multi_joined`
By default, `FastCRUD` joins all the data and returns it in a single dictionary.
Let's define two tables:
python
class User(Base):
__tablename__ = "user"
id = Column(Integer, primary_key=True)
name = Column(String)
tier_id = Column(Integer, ForeignKey("tier.id"))


class Tier(Base):
__tablename__ = "tier"
id = Column(Integer, primary_key=True)
name = Column(String, unique=True)


And join them with `FastCRUD`:

python
user_tier = await user_crud.get_joined(
db=db,
model=Tier,
join_on=User.tier_id == Tier.id,
join_type="left",
join_prefix="tier_",,
id=1
)


We'll get:

javascript
{
"id": 1,
"name": "Example",
"tier_id": 1,
"tier_name": "Free",
}


Now, if you want the joined data in a nested dictionary instead, you may just pass `nest_joins=True`:

python
user_tier = await user_crud.get_joined(
db=db,
model=Tier,
join_on=User.tier_id == Tier.id,
join_type="left",
join_prefix="tier_",
nest_joins=True,
id=1,
)


And you will get:

javascript
{
"id": 1,
"name": "Example",
"tier": {
"id": 1,
"name": "Free",
},
}


This works for both `get_joined` and `get_multi_joined`.

!!! WARNING
Note that the final `"_"` in the passed `"tier_"` is stripped.

What's Changed
- Reuse of `select` method in `FastCRUD`
- Skip count call when possible
- Add `one_or_none` parameter to FastCRUD `get` method
- Add `nest_joins` parameter to FastCRUD `get_joined` and `get_multi_joined`

New Contributors
- [JakNowy](https://github.com/JakNowy) made their first contribution in PR #51.

**Full Changelog**: [View the full changelog](https://github.com/igorbenav/fastcrud/compare/v0.11.0...v0.11.1)

0.11.0

Added
- Multiple primary keys support, a significant enhancement by dubusster in 31 🎉.
- Option to disable the count in `get_multi` and `get_multi_joined` methods for performance optimization.
- Fixes for a validation bug when `return_as_model` is set to `True`.
- Resolution of a bug concerning incorrect handling of `db_row` in methods.
- Correction of the `valid_methods` bug, which previously raised the wrong error type.
- Upgrade of `FastAPI` dependency to version `0.111.0`, ensuring compatibility with the latest FastAPI features.
- Achievement of 100% test coverage, with the addition of a workflow and badge to showcase this milestone.
- Inclusion of the changelog within the project documentation, providing a comprehensive history of changes directly to users.

Detailed Changes

Multiple Primary Keys Support
FastCRUD now accommodates models with multiple primary keys, facilitating more complex database designs. For models defined with more than one primary key, the endpoint creator automatically generates paths reflecting the primary keys' order. This feature extends support to primary keys named differently than `id`, enhancing the flexibility of FastCRUD's routing capabilities.

Example:
For a model with multiple primary keys, FastCRUD generates specific endpoints such as `/multi_pk/get/{id}/{uuid}`, accommodating the unique identification needs of complex data models.

Optional Count
The `get_multi` and `get_multi_joined` methods now feature an `return_total_count=False` parameter, allowing users to opt-out of receiving the total count in responses. This option can enhance performance by skipping potentially expensive count operations.

Behavior:
- By default, `return_total_count=True` is assumed, returning both data and a total count.
- When set to `False`, responses contain only the data array, omitting the total count for efficiency.

What's Changed
- Implementation of multiple primary keys support, addressing a significant flexibility requirement for advanced use cases.
- Introduction of optional count retrieval in multi-get methods, optimizing performance by eliminating unnecessary database queries.
- Several critical bug fixes, improving the stability and reliability of FastCRUD.
- Documentation enhancements, including the addition of a changelog section, ensuring users have access to detailed release information.
- Update to FastAPI `0.111.0`, ensuring compatibility with the latest enhancements in the FastAPI ecosystem.
- Achievement of 100% test coverage, marking a significant milestone in the project's commitment to reliability and quality assurance.

Relevant Contributors
- [dubusster](https://github.com/dubusster) made a notable contribution with the implementation of multiple primary keys support in PR #31.

**Full Changelog**: [View the full changelog](https://github.com/igorbenav/fastcrud/compare/v0.10.0...v0.11.0)

0.10.0

Added
- `select` statement functionality, thanks to dubusster's contribution in PR 28 🚀.
- Support for joined models in the `count` method through the `joins_config` parameter.
- Filters for joined models via the `filters` parameter in `JoinConfig`.
- Type checking workflow integrated with `mypy` alongside fixes for typing issues.
- Linting workflow established with `ruff`.

Detailed Changes

Select
The `select` method constructs a SQL Alchemy `Select` statement, offering flexibility in column selection, filtering, and sorting. It is designed to chain additional SQLAlchemy methods for complex queries.
[Docs here](https://igorbenav.github.io/fastcrud/usage/crud/#5-select) and [here](https://igorbenav.github.io/fastcrud/advanced/crud/#the-select-method).

Features:
- **Column Selection**: Choose columns via a Pydantic schema.
- **Sorting**: Define columns and their order for sorting.
- **Filtering**: Directly apply filters through keyword arguments.
- **Chaining**: Allow for chaining with other SQLAlchemy methods for advanced query construction.

Improved Joins
`JoinConfig` enhances FastCRUD queries by detailing join operations between models, offering configurations like model joining, conditions, prefixes, column selection through schemas, join types, aliases, and direct filtering. [Docs here](https://igorbenav.github.io/fastcrud/advanced/joins/).

Applying Joins in FastCRUD Methods
Detailed explanations and examples are provided for using joins in `count`, `get_joined`, and `get_multi_joined` methods to achieve complex data retrieval, including handling of many-to-many relationships.

What's Changed
- New `select` statement functionality added.
- Documentation and method improvements for select and joins.
- Integration of type checking and linting workflows.
- Version bump in pyproject.toml.

New Contributors
- [dubusster](https://github.com/dubusster) made their first contribution in PR #28.

**Full Changelog**: [View the full changelog](https://github.com/igorbenav/fastcrud/compare/v0.9.1...v0.10.0)

___

Page 1 of 3

© 2024 Safety CLI Cybersecurity Inc. All Rights Reserved.