Skip to content

Commit

Permalink
Merge pull request #56 from igorbenav/nested-responses
Browse files Browse the repository at this point in the history
Nested responses
  • Loading branch information
igorbenav authored Apr 22, 2024
2 parents 427806e + 346b540 commit 5e45aee
Show file tree
Hide file tree
Showing 10 changed files with 488 additions and 21 deletions.
74 changes: 74 additions & 0 deletions docs/advanced/joins.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,80 @@ tasks_with_users = await task_crud.get_joined(
)
```

#### Getting Joined Data Nested

Note that 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",
}
```

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.

### Complex Joins Using `JoinConfig`

When dealing with more complex join conditions, such as multiple joins, self-referential joins, or needing to specify aliases and filters, `JoinConfig` instances become the norm. They offer granular control over each join's aspects, enabling precise and efficient data retrieval.
Expand Down
104 changes: 104 additions & 0 deletions docs/changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,110 @@ The Changelog documents all notable changes made to FastCRUD. This includes new

___

## [0.11.1] - Apr 22, 2024

#### 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] - Apr 7, 2024

#### Added
Expand Down
3 changes: 3 additions & 0 deletions docs/usage/crud.md
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ get(
db: AsyncSession,
schema_to_select: Optional[type[BaseModel]] = None,
return_as_model: bool = False,
one_or_none: bool = False,
**kwargs: Any
) -> Optional[Union[dict, BaseModel]]
```
Expand Down Expand Up @@ -231,6 +232,7 @@ get_joined(
join_type: str = "left",
join_filters: Optional[dict] = None,
joins_config: Optional[list[JoinConfig]] = None,
nest_joins: bool = False,
**kwargs: Any,
) -> Optional[dict[str, Any]]
```
Expand Down Expand Up @@ -261,6 +263,7 @@ get_multi_joined(
join_type: str = "left",
alias: Optional[str] = None,
join_filters: Optional[dict] = None,
nest_joins: bool = False,
offset: int = 0,
limit: int = 100,
sort_columns: Optional[Union[str, list[str]]] = None,
Expand Down
Loading

0 comments on commit 5e45aee

Please sign in to comment.