Skip to content

Commit

Permalink
Merge pull request #26 from igorbenav/mutiple-models-joined
Browse files Browse the repository at this point in the history
Using `get_joined` and `get_multi_joined` for multiple models
  • Loading branch information
igorbenav authored Mar 14, 2024
2 parents 7ac2094 + 69a8960 commit 892a64a
Show file tree
Hide file tree
Showing 13 changed files with 507 additions and 99 deletions.
6 changes: 1 addition & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ pip install fastcrud
Or, if using poetry:

```sh
poetry add fastcrud
poetry add fastcrud
```

<h2>Usage</h2>
Expand Down Expand Up @@ -141,14 +141,10 @@ async def lifespan(app: FastAPI):
# FastAPI app
app = FastAPI(lifespan=lifespan)

# CRUD operations setup
crud = FastCRUD(Item)

# CRUD router setup
item_router = crud_router(
session=get_session,
model=Item,
crud=crud,
create_schema=ItemCreateSchema,
update_schema=ItemUpdateSchema,
path="/items",
Expand Down
68 changes: 68 additions & 0 deletions docs/advanced/crud.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,74 @@ item_count = await item_crud.count(
)
```

## Using `get_joined` and `get_multi_joined` for multiple models

To facilitate complex data relationships, `get_joined` and `get_multi_joined` can be configured to handle joins with multiple models. This is achieved using the `joins_config` parameter, where you can specify a list of `JoinConfig` instances, each representing a distinct join configuration.

#### Example: Joining User, Tier, and Department Models

Consider a scenario where you want to retrieve users along with their associated tier and department information. Here's how you can achieve this using `get_multi_joined`.

Start by creating a list of the multiple models to be joined:

```python hl_lines="1 3-10 12-19" title="Join Configurations"
from fastcrud import JoinConfig

joins_config = [
JoinConfig(
model=Tier,
join_on=User.tier_id == Tier.id,
join_prefix="tier_",
schema_to_select=TierSchema,
join_type="left",
),

JoinConfig(
model=Department,
join_on=User.department_id == Department.id,
join_prefix="dept_",
schema_to_select=DepartmentSchema,
join_type="inner",
)
]

users = await user_crud.get_multi_joined(
db=session,
schema_to_select=UserSchema,
joins_config=joins_config,
offset=0,
limit=10,
sort_columns='username',
sort_orders='asc'
)
```

Then just pass this list to joins_config:

```python hl_lines="10" title="Passing to get_multi_joined"
from fastcrud import JoinConfig

joins_config = [
...
]

users = await user_crud.get_multi_joined(
db=session,
schema_to_select=UserSchema,
joins_config=joins_config,
offset=0,
limit=10,
sort_columns='username',
sort_orders='asc'
)
```

In this example, users are joined with the `Tier` and `Department` models. The `join_on` parameter specifies the condition for the join, `join_prefix` assigns a prefix to columns from the joined models (to avoid naming conflicts), and `join_type` determines whether it's a left or inner join.

!!! WARNING

If both single join parameters and `joins_config` are used simultaneously, an error will be raised.

## Conclusion

The advanced features of FastCRUD, such as `allow_multiple` and support for advanced filters, empower developers to efficiently manage database records with complex conditions. By leveraging these capabilities, you can build more dynamic, robust, and scalable FastAPI applications that effectively interact with your data model.
26 changes: 14 additions & 12 deletions docs/usage/crud.md
Original file line number Diff line number Diff line change
Expand Up @@ -219,18 +219,19 @@ items = await item_crud.get_multi(db, offset=0, limit=10, sort_columns=['name'],

```python
get_joined(
db: AsyncSession,
join_model: type[ModelType],
join_prefix: Optional[str] = None,
join_on: Optional[Union[Join, None]] = None,
schema_to_select: Optional[type[BaseModel]] = None,
join_schema_to_select: Optional[type[BaseModel]] = None,
join_type: str = "left",
**kwargs: Any
db: AsyncSession,
join_model: Optional[type[DeclarativeBase]] = None,
join_prefix: Optional[str] = None,
join_on: Optional[Union[Join, BinaryExpression]] = None,
schema_to_select: Optional[type[BaseModel]] = None,
join_schema_to_select: Optional[type[BaseModel]] = None,
join_type: str = "left",
joins_config: Optional[list[JoinConfig]] = None,
**kwargs: Any,
) -> Optional[dict[str, Any]]
```

**Purpose**: To fetch a single record while performing a join operation with another model.
**Purpose**: To fetch a single record with one or multiple joins on other models.
**Usage Example**: Fetches order details for a specific order by joining with the Customer table, selecting specific columns as defined in OrderSchema and CustomerSchema.

```python
Expand All @@ -248,9 +249,9 @@ order_details = await order_crud.get_joined(
```python
get_multi_joined(
db: AsyncSession,
join_model: type[ModelType],
join_model: Optional[type[ModelType]] = None,
join_prefix: Optional[str] = None,
join_on: Optional[Join] = None,
join_on: Optional[Any] = None,
schema_to_select: Optional[type[BaseModel]] = None,
join_schema_to_select: Optional[type[BaseModel]] = None,
join_type: str = "left",
Expand All @@ -259,7 +260,8 @@ get_multi_joined(
sort_columns: Optional[Union[str, list[str]]] = None,
sort_orders: Optional[Union[str, list[str]]] = None,
return_as_model: bool = False,
**kwargs: Any
joins_config: Optional[list[JoinConfig]] = None,
**kwargs: Any,
) -> dict[str, Any]
```

Expand Down
3 changes: 2 additions & 1 deletion fastcrud/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from .crud.fast_crud import FastCRUD
from .endpoint.endpoint_creator import EndpointCreator
from .endpoint.crud_router import crud_router
from .crud.helper import JoinConfig

__all__ = ["FastCRUD", "EndpointCreator", "crud_router"]
__all__ = ["FastCRUD", "EndpointCreator", "crud_router", "JoinConfig"]
Loading

0 comments on commit 892a64a

Please sign in to comment.