96
96
5 . [ Alembic Migrations] ( #55-alembic-migrations )
97
97
6 . [ CRUD] ( #56-crud )
98
98
7 . [ Routes] ( #57-routes )
99
+ 1 . [ Paginated Responses] ( #571-paginated-responses )
99
100
8 . [ Caching] ( #58-caching )
100
101
9 . [ More Advanced Caching] ( #59-more-advanced-caching )
101
102
10 . [ ARQ Job Queues] ( #510-arq-job-queues )
@@ -412,6 +413,7 @@ First, you may want to take a look at the project structure and understand what
412
413
│ │ ├── __init__.py
413
414
│ │ ├── dependencies.py # Defines dependencies that can be reused across the API endpoints.
414
415
│ │ ├── exceptions.py # Contains custom exceptions for the API.
416
+ │ │ ├── paginated.py # Provides utilities for paginated responses in APIs
415
417
│ │ │
416
418
│ │ └── v1 # Version 1 of the API.
417
419
│ │ ├── __init__.py
@@ -690,10 +692,15 @@ from app.core.database import async_get_db
690
692
691
693
router = fastapi.APIRouter(tags = [" entities" ])
692
694
693
- @router.get (" /entities" , response_model = List[EntityRead])
694
- async def read_entities (db : Annotated[AsyncSession, Depends(async_get_db)]):
695
- entities = await crud_entities.get_multi(db = db)
696
- return entities
695
+ @router.get (" /entities/{id} " , response_model = List[EntityRead])
696
+ async def read_entities (
697
+ request : Request,
698
+ id : int ,
699
+ db : Annotated[AsyncSession, Depends(async_get_db)]
700
+ ):
701
+ entity = await crud_entities.get(db = db, id = id )
702
+
703
+ return entity
697
704
698
705
...
699
706
```
@@ -708,6 +715,71 @@ router = APIRouter(prefix="/v1") # this should be there already
708
715
router.include_router(entity_router)
709
716
```
710
717
718
+ #### 5.7.1 Paginated Responses
719
+ With the ` get_multi ` method we get a python ` dict ` with full suport for pagination:
720
+ ``` javascript
721
+ {
722
+ " data" : [
723
+ {
724
+ " id" : 4 ,
725
+ " name" : " User Userson" ,
726
+ " username" : " userson4" ,
727
+
728
+ " profile_image_url" : " https://profileimageurl.com"
729
+ },
730
+ {
731
+ " id" : 5 ,
732
+ " name" : " User Userson" ,
733
+ " username" : " userson5" ,
734
+
735
+ " profile_image_url" : " https://profileimageurl.com"
736
+ }
737
+ ],
738
+ " total_count" : 2 ,
739
+ " has_more" : false ,
740
+ " page" : 1 ,
741
+ " items_per_page" : 10
742
+ }
743
+ ```
744
+
745
+ And in the endpoint, we can import from ` app/api/paginated ` the following functions and Pydantic Schema:
746
+ ``` python
747
+ from app.api.paginated import (
748
+ PaginatedListResponse, # What you'll use as a response_model to validate
749
+ paginated_response, # Creates a paginated response based on the parameters
750
+ compute_offset # Calculate the offset for pagination ((page - 1) * items_per_page)
751
+ )
752
+ ```
753
+
754
+ Then let's create the endpoint:
755
+ ``` python
756
+ import fastapi
757
+
758
+ from app.schemas.entity imoport EntityRead
759
+ ...
760
+
761
+ @router.get (" /entities" , response_model = PaginatedListResponse[EntityRead])
762
+ async def read_entities (
763
+ request : Request,
764
+ db : Annotated[AsyncSession, Depends(async_get_db)],
765
+ page : int = 1 ,
766
+ items_per_page : int = 10
767
+ ):
768
+ entities_data = await crud_entity.get_multi(
769
+ db = db,
770
+ offset = compute_offset(page, items_per_page),
771
+ limit = items_per_page,
772
+ schema_to_select = UserRead,
773
+ is_deleted = False
774
+ )
775
+
776
+ return paginated_response(
777
+ crud_data = entities_data,
778
+ page = page,
779
+ items_per_page = items_per_page
780
+ )
781
+ ```
782
+
711
783
### 5.8 Caching
712
784
The ` cache ` decorator allows you to cache the results of FastAPI endpoint functions, enhancing response times and reducing the load on your application by storing and retrieving data in a cache.
713
785
0 commit comments