Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Preparations for 0.15.0 #163

Merged
merged 7 commits into from
Sep 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 27 additions & 0 deletions docs/advanced/crud.md
Original file line number Diff line number Diff line change
Expand Up @@ -292,6 +292,33 @@ items = await item_crud.upsert_multi(
# this will return the upserted data in the form of ItemSchema
```

### Customizing the Update Logic

To allow more granular control over the SQL `UPDATE` operation during an upsert, `upsert_multi` can accept an `update_override` argument. This allows for the specification of custom update logic using SQL expressions, like the `case` statement, to handle complex conditions.

```python
from sqlalchemy.sql import case

update_override = {
"name": case(
(Item.name.is_(None), stmt.excluded.name),
else_=Item.name
)
}

items = await item_crud.upsert_multi(
db=db,
instances=[
CreateItemSchema(name="Gadget", price=15.99),
],
update_override=update_override,
schema_to_select=ItemSchema,
return_as_model=True,
)
```

In the example above, the `name` field of the `Item` model will be updated to the new value only if the existing `name` field is `None`. Otherwise, it retains the existing `name`.

#### 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`.
Expand Down
59 changes: 25 additions & 34 deletions docs/advanced/endpoint.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,19 @@ FastCRUD automates the creation of CRUD (Create, Read, Update, Delete) endpoints

### Create

- **Endpoint**: `/create`
- **Endpoint**: `/{model}`
- **Method**: `POST`
- **Description**: Creates a new item in the database.
- **Request Body**: JSON object based on the `create_schema`.
- **Example Request**: `POST /items/create` with JSON body.
- **Example Request**: `POST /items` with JSON body.

### Read

- **Endpoint**: `/get/{id}`
- **Endpoint**: `/{model}/{id}`
- **Method**: `GET`
- **Description**: Retrieves a single item by its ID.
- **Path Parameters**: `id` - The ID of the item to retrieve.
- **Example Request**: `GET /items/get/1`.
- **Example Request**: `GET /items/1`.
- **Example Return**:
```javascript
{
Expand All @@ -33,13 +33,15 @@ FastCRUD automates the creation of CRUD (Create, Read, Update, Delete) endpoints

### Read Multiple

- **Endpoint**: `/get_multi`
- **Endpoint**: `/{model}`
- **Method**: `GET`
- **Description**: Retrieves multiple items with optional pagination.
- **Query Parameters**:
- `offset` (optional): The offset from where to start fetching items.
- `limit` (optional): The maximum number of items to return.
- **Example Request**: `GET /items/get_multi?offset=3&limit=4`.
- `page` (optional): The page number, starting from 1.
- `itemsPerPage` (optional): The number of items per page.
- **Example Request**: `GET /items?offset=3&limit=4`.
- **Example Return**:
```javascript
{
Expand Down Expand Up @@ -83,19 +85,9 @@ FastCRUD automates the creation of CRUD (Create, Read, Update, Delete) endpoints
],
"total_count": 50
}

```

### Read Paginated

- **Endpoint**: `/get_paginated`
- **Method**: `GET`
- **Description**: Retrieves multiple items with pagination.
- **Query Parameters**:
- `page`: The page number, starting from 1.
- `itemsPerPage`: The number of items per page.
- **Example Request**: `GET /items/get_paginated?page=1&itemsPerPage=3`.
- **Example Return**:
- **Example Paginated Request**: `GET /items?page=1&itemsPerPage=3`.
- **Example Paginated Return**:
```javascript
{
"data": [
Expand Down Expand Up @@ -134,48 +126,48 @@ FastCRUD automates the creation of CRUD (Create, Read, Update, Delete) endpoints
}
```

!!! WARNING
!!! NOTE

`_read_paginated` endpoint is getting deprecated and mixed into `_read_items` in the next major release.
Please use `_read_items` with optional `page` and `items_per_page` query params instead, to achieve pagination as before.
`_read_paginated` endpoint was deprecated and mixed into `_read_items` in the release `0.15.0`.
Simple `_read_items` behaviour persists with no breaking changes.

Read items paginated:
```sh
$ curl -X 'GET' \
'http://localhost:8000/users/get_multi?page=2&itemsPerPage=10' \
'http://localhost:8000/users?page=2&itemsPerPage=10' \
-H 'accept: application/json'
```

Read items unpaginated:
```sh
$ curl -X 'GET' \
'http://localhost:8000/users/get_multi?offset=0&limit=100' \
'http://localhost:8000/users?offset=0&limit=100' \
-H 'accept: application/json'
```


### Update

- **Endpoint**: `/update/{id}`
- **Endpoint**: `/{model}/{id}`
- **Method**: `PATCH`
- **Description**: Updates an existing item by its ID.
- **Path Parameters**: `id` - The ID of the item to update.
- **Request Body**: JSON object based on the `update_schema`.
- **Example Request**: `PATCH /items/update/1` with JSON body.
- **Example Request**: `PATCH /items/1` with JSON body.
- **Example Return**: `None`

### Delete

- **Endpoint**: `/delete/{id}`
- **Endpoint**: `/{model}/{id}`
- **Method**: `DELETE`
- **Description**: Deletes (soft delete if configured) an item by its ID.
- **Path Parameters**: `id` - The ID of the item to delete.
- **Example Request**: `DELETE /items/delete/1`.
- **Example Request**: `DELETE /items/1`.
- **Example Return**: `None`

### DB Delete (Hard Delete)

- **Endpoint**: `/db_delete/{id}` (Available if a `delete_schema` is provided)
- **Endpoint**: `/{model}/db_delete/{id}` (Available if a `delete_schema` is provided)
- **Method**: `DELETE`
- **Description**: Permanently deletes an item by its ID, bypassing the soft delete mechanism.
- **Path Parameters**: `id` - The ID of the item to hard delete.
Expand Down Expand Up @@ -251,7 +243,7 @@ app.include_router(my_router)

## Customizing Endpoint Names

You can customize the names of the auto generated endpoints by passing an `endpoint_names` dictionary when initializing the `EndpointCreator` or calling the `crud_router` function. This dictionary should map the CRUD operation names (`create`, `read`, `update`, `delete`, `db_delete`, `read_multi`, `read_paginated`) to your desired endpoint names.
You can customize the names of the auto generated endpoints by passing an `endpoint_names` dictionary when initializing the `EndpointCreator` or calling the `crud_router` function. This dictionary should map the CRUD operation names (`create`, `read`, `update`, `delete`, `db_delete`, `read_multi`) to your desired endpoint names.

### Example: Using `crud_router`

Expand All @@ -274,7 +266,6 @@ custom_endpoint_names = {
"update": "modify",
"delete": "remove",
"read_multi": "list",
"read_paginated": "paginate",
}

# Setup CRUD router with custom endpoint names
Expand Down Expand Up @@ -326,9 +317,9 @@ app.include_router(endpoint_creator.router)

You only need to pass the names of the endpoints you want to change in the `endpoint_names` `dict`.

!!! WARNING
!!! NOTE

`default_endpoint_names` for `EndpointCreator` are going to be changed to empty strings in the next major release.
`default_endpoint_names` for `EndpointCreator` were changed to empty strings in `0.15.0`.
See [this issue](https://github.com/igorbenav/fastcrud/issues/67) for more details.

## Extending `EndpointCreator`
Expand Down Expand Up @@ -551,7 +542,7 @@ app.include_router(endpoint_creator(

## 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.
FastCRUD provides filtering capabilities, allowing you to filter query results based on various conditions. Filters can be applied to `read_multi` endpoint. This section explains how to configure and use filters in FastCRUD.

### Defining Filters

Expand Down Expand Up @@ -607,7 +598,7 @@ app.include_router(
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
GET /yourmodel?page=1&itemsPerPage=3&tier_id=1&name=Alice
```

### Custom Filter Validation
Expand Down
8 changes: 2 additions & 6 deletions fastcrud/endpoint/crud_router.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ def crud_router(
create_deps: Sequence[Callable] = [],
read_deps: Sequence[Callable] = [],
read_multi_deps: Sequence[Callable] = [],
read_paginated_deps: Sequence[Callable] = [],
update_deps: Sequence[Callable] = [],
delete_deps: Sequence[Callable] = [],
db_delete_deps: Sequence[Callable] = [],
Expand Down Expand Up @@ -60,7 +59,6 @@ def crud_router(
create_deps: Optional list of functions to be injected as dependencies for the create endpoint.
read_deps: Optional list of functions to be injected as dependencies for the read endpoint.
read_multi_deps: Optional list of functions to be injected as dependencies for the read multiple items endpoint.
read_paginated_deps: Optional list of functions to be injected as dependencies for the read paginated endpoint.
update_deps: Optional list of functions to be injected as dependencies for the update endpoint.
delete_deps: Optional list of functions to be injected as dependencies for the delete endpoint.
db_delete_deps: Optional list of functions to be injected as dependencies for the hard delete endpoint.
Expand All @@ -71,9 +69,9 @@ def crud_router(
deleted_at_column: Optional column name to use for storing the timestamp of a soft delete. Defaults to `"deleted_at"`.
updated_at_column: Optional column name to use for storing the timestamp of an update. Defaults to `"updated_at"`.
endpoint_names: Optional dictionary to customize endpoint names for CRUD operations. Keys are operation types
(`"create"`, `"read"`, `"update"`, `"delete"`, `"db_delete"`, `"read_multi"`, `"read_paginated"`), and
(`"create"`, `"read"`, `"update"`, `"delete"`, `"db_delete"`, `"read_multi"`), and
values are the custom names to use. Unspecified operations will use default names.
filter_config: Optional `FilterConfig` instance or dictionary to configure filters for the `read_multi` and `read_paginated` endpoints.
filter_config: Optional `FilterConfig` instance or dictionary to configure filters for the `read_multi` endpoint.

Returns:
Configured `APIRouter` instance with the CRUD endpoints.
Expand Down Expand Up @@ -457,7 +455,6 @@ async def add_routes_to_router(self, ...):
"delete": "remove_task",
"db_delete": "permanently_remove_task",
"read_multi": "list_tasks",
"read_paginated": "paginate_tasks",
},
)
```
Expand Down Expand Up @@ -550,7 +547,6 @@ async def add_routes_to_router(self, ...):
create_deps=create_deps,
read_deps=read_deps,
read_multi_deps=read_multi_deps,
read_paginated_deps=read_paginated_deps,
update_deps=update_deps,
delete_deps=delete_deps,
db_delete_deps=db_delete_deps,
Expand Down
Loading
Loading