Repository: igorbenav/fastcrud
Pull request #163 (2024-09-18 05:11:37)

Preparations for `0.15.0`


Patch:
diff --git a/docs/advanced/crud.md b/docs/advanced/crud.md
index 709a088..fe45d3d 100644
--- a/docs/advanced/crud.md
+++ b/docs/advanced/crud.md
@@ -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`.
diff --git a/docs/advanced/endpoint.md b/docs/advanced/endpoint.md
index caff2a0..f65a869 100644
--- a/docs/advanced/endpoint.md
+++ b/docs/advanced/endpoint.md
@@ -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
 {
@@ -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
 {
@@ -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": [
@@ -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.
@@ -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`
 
@@ -274,7 +266,6 @@ custom_endpoint_names = {
     "update": "modify",
     "delete": "remove",
     "read_multi": "list",
-    "read_paginated": "paginate",
 }
 
 # Setup CRUD router with custom endpoint names
@@ -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`
@@ -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
 
@@ -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
diff --git a/fastcrud/endpoint/crud_router.py b/fastcrud/endpoint/crud_router.py
index eeaa402..c8cc0cd 100644
--- a/fastcrud/endpoint/crud_router.py
+++ b/fastcrud/endpoint/crud_router.py
@@ -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] = [],
@@ -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.
@@ -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.
@@ -457,7 +455,6 @@ def crud_router(
                 "delete": "remove_task",
                 "db_delete": "permanently_remove_task",
                 "read_multi": "list_tasks",
-                "read_paginated": "paginate_tasks",
             },
         )
         ```
@@ -550,7 +547,6 @@ def crud_router(
         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,
diff --git a/fastcrud/endpoint/endpoint_creator.py b/fastcrud/endpoint/endpoint_creator.py
index 8dd5d82..f4f9694 100644
--- a/fastcrud/endpoint/endpoint_creator.py
+++ b/fastcrud/endpoint/endpoint_creator.py
@@ -1,6 +1,5 @@
 from typing import Type, Optional, Callable, Sequence, Union
 from enum import Enum
-import warnings
 
 from fastapi import Depends, Body, Query, APIRouter
 from pydantic import ValidationError
@@ -13,7 +12,11 @@ from fastcrud.types import (
     ModelType,
     UpdateSchemaType,
 )
-from ..exceptions.http_exceptions import DuplicateValueException, NotFoundException
+from ..exceptions.http_exceptions import (
+    DuplicateValueException,
+    NotFoundException,
+    BadRequestException,
+)
 from ..paginated.helper import compute_offset
 from ..paginated.response import paginated_response
 from .helper import (
@@ -52,9 +55,9 @@ class EndpointCreator:
         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.
 
     Raises:
         ValueError: If both `included_methods` and `deleted_methods` are provided.
@@ -273,24 +276,14 @@ class EndpointCreator:
         self.deleted_at_column = deleted_at_column
         self.updated_at_column = updated_at_column
         self.default_endpoint_names = {
-            "create": "create",
-            "read": "get",
-            "update": "update",
-            "delete": "delete",
+            "create": "",
+            "read": "",
+            "update": "",
+            "delete": "",
             "db_delete": "db_delete",
-            "read_multi": "get_multi",
-            "read_paginated": "get_paginated",
+            "read_multi": "",
         }
         self.endpoint_names = {**self.default_endpoint_names, **(endpoint_names or {})}
-        if self.endpoint_names == self.default_endpoint_names:
-            warnings.warn(
-                "Old default_endpoint_names are getting deprecated. "
-                "Default values are going to be replaced by empty strings, "
-                "resulting in plain endpoint names. "
-                "For details see:"
-                " https://github.com/igorbenav/fastcrud/issues/67",
-                DeprecationWarning,
-            )
         if filter_config:
             if isinstance(filter_config, dict):
                 filter_config = FilterConfig(**filter_config)
@@ -347,59 +340,49 @@ class EndpointCreator:
 
         async def endpoint(
             db: AsyncSession = Depends(self.session),
+            offset: Optional[int] = Query(
+                None, description="Offset for unpaginated queries"
+            ),
+            limit: Optional[int] = Query(
+                None, description="Limit for unpaginated queries"
+            ),
             page: Optional[int] = Query(None, alias="page", description="Page number"),
             items_per_page: Optional[int] = Query(
                 None, alias="itemsPerPage", description="Number of items per page"
             ),
             filters: dict = Depends(dynamic_filters),
         ):
-            if not (page and items_per_page):
-                return await self.crud.get_multi(db, offset=0, limit=100, **filters)
-
-            offset = compute_offset(page=page, items_per_page=items_per_page)
-            crud_data = await self.crud.get_multi(
-                db, offset=offset, limit=items_per_page, **filters
-            )
+            is_paginated = (page is not None) and (items_per_page is not None)
+            has_offset_limit = (offset is not None) and (limit is not None)
 
-            return paginated_response(
-                crud_data=crud_data, page=page, items_per_page=items_per_page
-            )  # pragma: no cover
-
-        return endpoint
+            if is_paginated and has_offset_limit:
+                raise BadRequestException(
+                    detail="Conflicting parameters: Use either 'page' and 'itemsPerPage' for paginated results or 'offset' and 'limit' for specific range queries."
+                )
 
-    def _read_paginated(self):
-        """Creates an endpoint for reading multiple items from the database with pagination."""
-        dynamic_filters = _create_dynamic_filters(self.filter_config, self.column_types)
-        warnings.warn(
-            "_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."
-            "Simple _read_items behaviour persists with no breaking changes.",
-            DeprecationWarning,
-        )
+            if is_paginated:
+                offset = compute_offset(page=page, items_per_page=items_per_page)  # type: ignore
+                limit = items_per_page
+                crud_data = await self.crud.get_multi(
+                    db, offset=offset, limit=limit, **filters
+                )
+                return paginated_response(
+                    crud_data=crud_data,
+                    page=page, # type: ignore
+                    items_per_page=items_per_page,  # type: ignore
+                )
 
-        async def endpoint(
-            db: AsyncSession = Depends(self.session),
-            page: int = Query(
-                1, alias="page", description="Page number, starting from 1"
-            ),
-            items_per_page: int = Query(
-                10, alias="itemsPerPage", description="Number of items per page"
-            ),
-            filters: dict = Depends(dynamic_filters),
-        ):
-            if not (page and items_per_page):  # pragma: no cover
-                return await self.crud.get_multi(db, offset=0, limit=100, **filters)
+            if not has_offset_limit:
+                offset = 0
+                limit = 100
 
-            offset = compute_offset(page=page, items_per_page=items_per_page)
             crud_data = await self.crud.get_multi(
-                db, offset=offset, limit=items_per_page, **filters
+                db,
+                offset=offset, # type: ignore
+                limit=limit, # type: ignore
+                **filters,
             )
-
-            return paginated_response(
-                crud_data=crud_data, page=page, items_per_page=items_per_page
-            )  # pragma: no cover
+            return crud_data  # pragma: no cover
 
         return endpoint
 
@@ -463,7 +446,6 @@ class EndpointCreator:
         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] = [],
@@ -480,7 +462,6 @@ class EndpointCreator:
             create_deps: List of functions to be injected as dependencies for the create endpoint.
             read_deps: List of functions to be injected as dependencies for the read endpoint.
             read_multi_deps: List of functions to be injected as dependencies for the read multiple items endpoint.
-            read_paginated_deps: List of functions to be injected as dependencies for the read paginated endpoint.
             update_deps: List of functions to be injected as dependencies for the update endpoint.
             delete_deps: List of functions to be injected as dependencies for the delete endpoint.
             db_delete_deps: List of functions to be injected as dependencies for the hard delete endpoint.
@@ -538,7 +519,6 @@ class EndpointCreator:
                 "create",
                 "read",
                 "read_multi",
-                "read_paginated",
                 "update",
                 "delete",
                 "db_delete",
@@ -598,19 +578,6 @@ class EndpointCreator:
                 description=f"Read multiple {self.model.__name__} rows from the database with a limit and an offset.",
             )
 
-        if ("read_paginated" in included_methods) and (
-            "read_paginated" not in deleted_methods
-        ):
-            self.router.add_api_route(
-                self._get_endpoint_path(operation="read_paginated"),
-                self._read_paginated(),
-                methods=["GET"],
-                include_in_schema=self.include_in_schema,
-                tags=self.tags,
-                dependencies=_inject_dependencies(read_paginated_deps),
-                description=f"Read multiple {self.model.__name__} rows from the database with pagination.",
-            )
-
         if ("update" in included_methods) and ("update" not in deleted_methods):
             self.router.add_api_route(
                 self._get_endpoint_path(operation="update"),
diff --git a/fastcrud/endpoint/helper.py b/fastcrud/endpoint/helper.py
index 4971026..32677d1 100644
--- a/fastcrud/endpoint/helper.py
+++ b/fastcrud/endpoint/helper.py
@@ -1,6 +1,5 @@
 import inspect
 from typing import Optional, Union, Annotated, Sequence, Callable, TypeVar, Any
-import warnings
 
 from pydantic import BaseModel, Field
 from pydantic.functional_validators import field_validator
@@ -22,7 +21,6 @@ class CRUDMethods(BaseModel):
                 "create",
                 "read",
                 "read_multi",
-                "read_paginated",
                 "update",
                 "delete",
                 "db_delete",
@@ -36,7 +34,6 @@ class CRUDMethods(BaseModel):
             "create",
             "read",
             "read_multi",
-            "read_paginated",
             "update",
             "delete",
             "db_delete",
@@ -127,42 +124,20 @@ def _extract_unique_columns(
     return unique_columns
 
 
-def _temporary_dependency_handling(
-    funcs: Optional[Sequence[Callable]] = None,
-) -> Union[Sequence[params.Depends], None]:  # pragma: no cover
-    """
-    Checks if any function in the provided sequence is an instance of params.Depends.
-    Issues a deprecation warning once if such instances are found, and returns the sequence if any params.Depends are found.
-
-    Args:
-        funcs: Optional sequence of callables or params.Depends instances.
-    """
-    if funcs is not None:
-        if any(isinstance(func, params.Depends) for func in funcs):
-            warnings.warn(
-                "Passing a function wrapped in `Depends` directly to dependency handlers is deprecated and will be removed in version 0.15.0.",
-                DeprecationWarning,
-                stacklevel=2,
-            )
-            return [
-                func if isinstance(func, params.Depends) else Depends(func)
-                for func in funcs
-            ]
-    return None
-
-
 def _inject_dependencies(
     funcs: Optional[Sequence[Callable]] = None,
 ) -> Optional[Sequence[params.Depends]]:
     """Wraps a list of functions in FastAPI's Depends."""
-    temp_handling = _temporary_dependency_handling(funcs)
-    if temp_handling is not None:  # pragma: no cover
-        return temp_handling
+    if funcs is None:
+        return None
 
-    if funcs is not None:
-        return [Depends(func) for func in funcs]
+    for func in funcs:
+        if not callable(func):
+            raise TypeError(
+                f"All dependencies must be callable. Got {type(func)} instead."
+            )
 
-    return None
+    return [Depends(func) for func in funcs]
 
 
 def _apply_model_pk(**pkeys: dict[str, type]):


Test patch:
diff --git a/tests/sqlalchemy/conftest.py b/tests/sqlalchemy/conftest.py
index c8283ee..af429a7 100644
--- a/tests/sqlalchemy/conftest.py
+++ b/tests/sqlalchemy/conftest.py
@@ -481,6 +481,14 @@ def client(
             delete_schema=delete_schema,
             path="/test",
             tags=["test"],
+            endpoint_names={
+                "create": "create",
+                "read": "get",
+                "update": "update",
+                "delete": "delete",
+                "db_delete": "db_delete",
+                "read_multi": "get_multi",
+            },
         )
     )
 
@@ -494,6 +502,14 @@ def client(
             delete_schema=tier_delete_schema,
             path="/tier",
             tags=["tier"],
+            endpoint_names={
+                "create": "create",
+                "read": "get",
+                "update": "update",
+                "delete": "delete",
+                "db_delete": "db_delete",
+                "read_multi": "get_multi",
+            },
         )
     )
 
@@ -508,6 +524,14 @@ def client(
             read_deps=[test_read_dep],
             path="/multi_pk",
             tags=["multi_pk"],
+            endpoint_names={
+                "create": "create",
+                "read": "get",
+                "update": "update",
+                "delete": "delete",
+                "db_delete": "db_delete",
+                "read_multi": "get_multi",
+            },
         )
     )
 
@@ -531,6 +555,14 @@ def filtered_client(
             filter_config=FilterConfig(tier_id=None, name=None),
             path="/test",
             tags=["test"],
+            endpoint_names={
+                "create": "create",
+                "read": "get",
+                "update": "update",
+                "delete": "delete",
+                "db_delete": "db_delete",
+                "read_multi": "get_multi",
+            },
         )
     )
 
@@ -554,6 +586,14 @@ def dict_filtered_client(
             filter_config={"tier_id": None, "name": None},
             path="/test",
             tags=["test"],
+            endpoint_names={
+                "create": "create",
+                "read": "get",
+                "update": "update",
+                "delete": "delete",
+                "db_delete": "db_delete",
+                "read_multi": "get_multi",
+            },
         )
     )
 
@@ -578,6 +618,14 @@ def invalid_filtered_client(
             filter_config=filter_config,
             path="/test",
             tags=["test"],
+            endpoint_names={
+                "create": "create",
+                "read": "get",
+                "update": "update",
+                "delete": "delete",
+                "db_delete": "db_delete",
+                "read_multi": "get_multi",
+            },
         )
 
 
@@ -593,4 +641,12 @@ def endpoint_creator(test_model, async_session) -> EndpointCreator:
         delete_schema=DeleteSchemaTest,
         path="/custom_test",
         tags=["custom_test"],
+        endpoint_names={
+            "create": "create",
+            "read": "get",
+            "update": "update",
+            "delete": "delete",
+            "db_delete": "db_delete",
+            "read_multi": "get_multi",
+        },
     )
diff --git a/tests/sqlalchemy/core/test_valid_methods.py b/tests/sqlalchemy/core/test_valid_methods.py
index 0d9465b..cc23468 100644
--- a/tests/sqlalchemy/core/test_valid_methods.py
+++ b/tests/sqlalchemy/core/test_valid_methods.py
@@ -22,7 +22,6 @@ def test_crud_methods_default_methods():
         "create",
         "read",
         "read_multi",
-        "read_paginated",
         "update",
         "delete",
         "db_delete",
diff --git a/tests/sqlalchemy/endpoint/test_custom_endpoint_creator.py b/tests/sqlalchemy/endpoint/test_custom_endpoint_creator.py
index 0b5969a..c13ac6b 100644
--- a/tests/sqlalchemy/endpoint/test_custom_endpoint_creator.py
+++ b/tests/sqlalchemy/endpoint/test_custom_endpoint_creator.py
@@ -19,7 +19,6 @@ class CustomEndpointCreator(EndpointCreator):
         create_deps: list[Callable] = [],
         read_deps: list[Callable] = [],
         read_multi_deps: list[Callable] = [],
-        read_paginated_deps: list[Callable] = [],
         update_deps: list[Callable] = [],
         delete_deps: list[Callable] = [],
         db_delete_deps: list[Callable] = [],
@@ -30,7 +29,6 @@ class CustomEndpointCreator(EndpointCreator):
             create_deps,
             read_deps,
             read_multi_deps,
-            read_paginated_deps,
             update_deps,
             delete_deps,
             db_delete_deps,
@@ -59,6 +57,14 @@ async def test_custom_endpoint_creator(
         endpoint_creator=CustomEndpointCreator,
         path="/custom",
         tags=["Test"],
+        endpoint_names={
+            "create": "create",
+            "read": "get",
+            "update": "update",
+            "delete": "delete",
+            "db_delete": "db_delete",
+            "read_multi": "get_multi",
+        },
     )
 
     client.app.include_router(custom_router)
diff --git a/tests/sqlalchemy/endpoint/test_deleted_methods.py b/tests/sqlalchemy/endpoint/test_deleted_methods.py
index bfa8209..633c766 100644
--- a/tests/sqlalchemy/endpoint/test_deleted_methods.py
+++ b/tests/sqlalchemy/endpoint/test_deleted_methods.py
@@ -16,6 +16,14 @@ async def test_deleted_methods(
         deleted_methods=["delete"],
         path="/test_custom",
         tags=["Test"],
+        endpoint_names={
+            "create": "create",
+            "read": "get",
+            "update": "update",
+            "delete": "delete",
+            "db_delete": "db_delete",
+            "read_multi": "get_multi",
+        },
     )
 
     client.app.include_router(custom_router)
diff --git a/tests/sqlalchemy/endpoint/test_get_paginated.py b/tests/sqlalchemy/endpoint/test_get_paginated.py
index 27785d1..d6183ab 100644
--- a/tests/sqlalchemy/endpoint/test_get_paginated.py
+++ b/tests/sqlalchemy/endpoint/test_get_paginated.py
@@ -2,94 +2,6 @@ import pytest
 from fastapi.testclient import TestClient
 
 
-@pytest.mark.asyncio
-async def test_read_paginated(client: TestClient, async_session, test_model, test_data):
-    for data in test_data:
-        new_item = test_model(**data)
-        async_session.add(new_item)
-    await async_session.commit()
-
-    page = 1
-    items_per_page = 5
-
-    response = client.get(
-        f"/test/get_paginated?page={page}&itemsPerPage={items_per_page}"
-    )
-
-    assert response.status_code == 200
-
-    data = response.json()
-
-    assert "data" in data
-    assert "total_count" in data
-    assert "page" in data
-    assert "items_per_page" in data
-    assert "has_more" in data
-
-    assert len(data["data"]) > 0
-    assert len(data["data"]) <= items_per_page
-
-    test_item = test_data[0]
-    assert any(item["name"] == test_item["name"] for item in data["data"])
-
-    assert data["page"] == page
-    assert data["items_per_page"] == items_per_page
-
-
-@pytest.mark.asyncio
-async def test_read_paginated_with_filters(
-    filtered_client: TestClient, async_session, test_model, test_data
-):
-    for data in test_data:
-        new_item = test_model(**data)
-        async_session.add(new_item)
-    await async_session.commit()
-
-    page = 1
-    items_per_page = 5
-
-    tier_id = 1
-    response = filtered_client.get(
-        f"/test/get_paginated?page={page}&itemsPerPage={items_per_page}&tier_id={tier_id}"
-    )
-
-    assert response.status_code == 200
-    data = response.json()
-
-    assert "data" in data
-    assert "total_count" in data
-    assert "page" in data
-    assert "items_per_page" in data
-    assert "has_more" in data
-
-    assert len(data["data"]) > 0
-    assert len(data["data"]) <= items_per_page
-
-    for item in data["data"]:
-        assert item["tier_id"] == tier_id
-
-    name = "Alice"
-    response = filtered_client.get(
-        f"/test/get_paginated?page={page}&itemsPerPage={items_per_page}&name={name}"
-    )
-
-    assert response.status_code == 200
-    data = response.json()
-
-    assert "data" in data
-    assert "total_count" in data
-    assert "page" in data
-    assert "items_per_page" in data
-    assert "has_more" in data
-
-    assert len(data["data"]) > 0
-    assert len(data["data"]) <= items_per_page
-
-    for item in data["data"]:
-        assert item["name"] == name
-
-
-# ------ the following tests will completely replace the current ones in the next version of fastcrud ------
 @pytest.mark.asyncio
 async def test_read_items_with_pagination(
     client: TestClient, async_session, test_model, test_data
diff --git a/tests/sqlalchemy/endpoint/test_included_methods.py b/tests/sqlalchemy/endpoint/test_included_methods.py
index 149805c..6d12887 100644
--- a/tests/sqlalchemy/endpoint/test_included_methods.py
+++ b/tests/sqlalchemy/endpoint/test_included_methods.py
@@ -16,6 +16,14 @@ async def test_included_methods(
         included_methods=["create", "read"],
         path="/test_custom",
         tags=["Test"],
+        endpoint_names={
+            "create": "create",
+            "read": "get",
+            "update": "update",
+            "delete": "delete",
+            "db_delete": "db_delete",
+            "read_multi": "get_multi",
+        },
     )
 
     client.app.include_router(custom_router)
diff --git a/tests/sqlmodel/conftest.py b/tests/sqlmodel/conftest.py
index 63baef3..95232a2 100644
--- a/tests/sqlmodel/conftest.py
+++ b/tests/sqlmodel/conftest.py
@@ -469,6 +469,14 @@ def client(
             delete_schema=delete_schema,
             path="/test",
             tags=["test"],
+            endpoint_names={
+                "create": "create",
+                "read": "get",
+                "update": "update",
+                "delete": "delete",
+                "db_delete": "db_delete",
+                "read_multi": "get_multi",
+            },
         )
     )
 
@@ -482,6 +490,14 @@ def client(
             delete_schema=tier_delete_schema,
             path="/tier",
             tags=["tier"],
+            endpoint_names={
+                "create": "create",
+                "read": "get",
+                "update": "update",
+                "delete": "delete",
+                "db_delete": "db_delete",
+                "read_multi": "get_multi",
+            },
         )
     )
 
@@ -496,6 +512,14 @@ def client(
             delete_schema=multi_pk_test_schema,
             path="/multi_pk",
             tags=["multi_pk"],
+            endpoint_names={
+                "create": "create",
+                "read": "get",
+                "update": "update",
+                "delete": "delete",
+                "db_delete": "db_delete",
+                "read_multi": "get_multi",
+            },
         )
     )
 
@@ -523,6 +547,14 @@ def filtered_client(
             filter_config=FilterConfig(tier_id=None, name=None),
             path="/test",
             tags=["test"],
+            endpoint_names={
+                "create": "create",
+                "read": "get",
+                "update": "update",
+                "delete": "delete",
+                "db_delete": "db_delete",
+                "read_multi": "get_multi",
+            },
         )
     )
 
@@ -550,6 +582,14 @@ def dict_filtered_client(
             filter_config={"tier_id": None, "name": None},
             path="/test",
             tags=["test"],
+            endpoint_names={
+                "create": "create",
+                "read": "get",
+                "update": "update",
+                "delete": "delete",
+                "db_delete": "db_delete",
+                "read_multi": "get_multi",
+            },
         )
     )
 
@@ -578,6 +618,14 @@ def invalid_filtered_client(
             filter_config=filter_config,
             path="/test",
             tags=["test"],
+            endpoint_names={
+                "create": "create",
+                "read": "get",
+                "update": "update",
+                "delete": "delete",
+                "db_delete": "db_delete",
+                "read_multi": "get_multi",
+            },
         )
 
 
@@ -593,4 +641,12 @@ def endpoint_creator(test_model, async_session) -> EndpointCreator:
         delete_schema=DeleteSchemaTest,
         path="/custom_test",
         tags=["custom_test"],
+        endpoint_names={
+            "create": "create",
+            "read": "get",
+            "update": "update",
+            "delete": "delete",
+            "db_delete": "db_delete",
+            "read_multi": "get_multi",
+        },
     )
diff --git a/tests/sqlmodel/core/test_valid_methods.py b/tests/sqlmodel/core/test_valid_methods.py
index 0d9465b..cc23468 100644
--- a/tests/sqlmodel/core/test_valid_methods.py
+++ b/tests/sqlmodel/core/test_valid_methods.py
@@ -22,7 +22,6 @@ def test_crud_methods_default_methods():
         "create",
         "read",
         "read_multi",
-        "read_paginated",
         "update",
         "delete",
         "db_delete",
diff --git a/tests/sqlmodel/endpoint/test_custom_endpoint_creator.py b/tests/sqlmodel/endpoint/test_custom_endpoint_creator.py
index 0b5969a..c13ac6b 100644
--- a/tests/sqlmodel/endpoint/test_custom_endpoint_creator.py
+++ b/tests/sqlmodel/endpoint/test_custom_endpoint_creator.py
@@ -19,7 +19,6 @@ class CustomEndpointCreator(EndpointCreator):
         create_deps: list[Callable] = [],
         read_deps: list[Callable] = [],
         read_multi_deps: list[Callable] = [],
-        read_paginated_deps: list[Callable] = [],
         update_deps: list[Callable] = [],
         delete_deps: list[Callable] = [],
         db_delete_deps: list[Callable] = [],
@@ -30,7 +29,6 @@ class CustomEndpointCreator(EndpointCreator):
             create_deps,
             read_deps,
             read_multi_deps,
-            read_paginated_deps,
             update_deps,
             delete_deps,
             db_delete_deps,
@@ -59,6 +57,14 @@ async def test_custom_endpoint_creator(
         endpoint_creator=CustomEndpointCreator,
         path="/custom",
         tags=["Test"],
+        endpoint_names={
+            "create": "create",
+            "read": "get",
+            "update": "update",
+            "delete": "delete",
+            "db_delete": "db_delete",
+            "read_multi": "get_multi",
+        },
     )
 
     client.app.include_router(custom_router)
diff --git a/tests/sqlmodel/endpoint/test_deleted_methods.py b/tests/sqlmodel/endpoint/test_deleted_methods.py
index bfa8209..633c766 100644
--- a/tests/sqlmodel/endpoint/test_deleted_methods.py
+++ b/tests/sqlmodel/endpoint/test_deleted_methods.py
@@ -16,6 +16,14 @@ async def test_deleted_methods(
         deleted_methods=["delete"],
         path="/test_custom",
         tags=["Test"],
+        endpoint_names={
+            "create": "create",
+            "read": "get",
+            "update": "update",
+            "delete": "delete",
+            "db_delete": "db_delete",
+            "read_multi": "get_multi",
+        },
     )
 
     client.app.include_router(custom_router)
diff --git a/tests/sqlmodel/endpoint/test_get_paginated.py b/tests/sqlmodel/endpoint/test_get_paginated.py
index 27785d1..d6183ab 100644
--- a/tests/sqlmodel/endpoint/test_get_paginated.py
+++ b/tests/sqlmodel/endpoint/test_get_paginated.py
@@ -2,94 +2,6 @@ import pytest
 from fastapi.testclient import TestClient
 
 
-@pytest.mark.asyncio
-async def test_read_paginated(client: TestClient, async_session, test_model, test_data):
-    for data in test_data:
-        new_item = test_model(**data)
-        async_session.add(new_item)
-    await async_session.commit()
-
-    page = 1
-    items_per_page = 5
-
-    response = client.get(
-        f"/test/get_paginated?page={page}&itemsPerPage={items_per_page}"
-    )
-
-    assert response.status_code == 200
-
-    data = response.json()
-
-    assert "data" in data
-    assert "total_count" in data
-    assert "page" in data
-    assert "items_per_page" in data
-    assert "has_more" in data
-
-    assert len(data["data"]) > 0
-    assert len(data["data"]) <= items_per_page
-
-    test_item = test_data[0]
-    assert any(item["name"] == test_item["name"] for item in data["data"])
-
-    assert data["page"] == page
-    assert data["items_per_page"] == items_per_page
-
-
-@pytest.mark.asyncio
-async def test_read_paginated_with_filters(
-    filtered_client: TestClient, async_session, test_model, test_data
-):
-    for data in test_data:
-        new_item = test_model(**data)
-        async_session.add(new_item)
-    await async_session.commit()
-
-    page = 1
-    items_per_page = 5
-
-    tier_id = 1
-    response = filtered_client.get(
-        f"/test/get_paginated?page={page}&itemsPerPage={items_per_page}&tier_id={tier_id}"
-    )
-
-    assert response.status_code == 200
-    data = response.json()
-
-    assert "data" in data
-    assert "total_count" in data
-    assert "page" in data
-    assert "items_per_page" in data
-    assert "has_more" in data
-
-    assert len(data["data"]) > 0
-    assert len(data["data"]) <= items_per_page
-
-    for item in data["data"]:
-        assert item["tier_id"] == tier_id
-
-    name = "Alice"
-    response = filtered_client.get(
-        f"/test/get_paginated?page={page}&itemsPerPage={items_per_page}&name={name}"
-    )
-
-    assert response.status_code == 200
-    data = response.json()
-
-    assert "data" in data
-    assert "total_count" in data
-    assert "page" in data
-    assert "items_per_page" in data
-    assert "has_more" in data
-
-    assert len(data["data"]) > 0
-    assert len(data["data"]) <= items_per_page
-
-    for item in data["data"]:
-        assert item["name"] == name
-
-
-# ------ the following tests will completely replace the current ones in the next version of fastcrud ------
 @pytest.mark.asyncio
 async def test_read_items_with_pagination(
     client: TestClient, async_session, test_model, test_data
diff --git a/tests/sqlmodel/endpoint/test_included_methods.py b/tests/sqlmodel/endpoint/test_included_methods.py
index 149805c..6d12887 100644
--- a/tests/sqlmodel/endpoint/test_included_methods.py
+++ b/tests/sqlmodel/endpoint/test_included_methods.py
@@ -16,6 +16,14 @@ async def test_included_methods(
         included_methods=["create", "read"],
         path="/test_custom",
         tags=["Test"],
+        endpoint_names={
+            "create": "create",
+            "read": "get",
+            "update": "update",
+            "delete": "delete",
+            "db_delete": "db_delete",
+            "read_multi": "get_multi",
+        },
     )
 
     client.app.include_router(custom_router)