4747- Easy redis caching
4848- Easy client-side caching
4949- ARQ integration for task queue
50+ - Efficient querying (only queries what's needed)
5051- Easily extendable
5152- Flexible
5253- Easy running with docker compose
6364#### Features
6465- [ ] Add a Rate Limiter decorator
6566- [ ] Add mongoDB support
67+ - [ ] Add support in schema_to_select for dict as well as Pydantic Schema
6668
6769#### Security
6870- [x] FastAPI docs behind authentication and hidden based on the environment
@@ -403,12 +405,19 @@ First, you may want to take a look at the project structure and understand what
403405└── src # Source code directory.
404406 ├── __init__.py # Initialization file for the src package.
405407 ├── alembic.ini # Configuration file for Alembic (database migration tool).
408+ ├── poetry.lock
409+ ├── pyproject.toml # Configuration file for Poetry, lists project dependencies.
410+ │
406411 ├── app # Main application directory.
407412 │ ├── __init__.py # Initialization file for the app package.
413+ │ ├── main.py # Entry point that imports and creates the FastAPI application instance.
414+ │ ├── worker.py # Worker script for handling background tasks.
415+ │ │
408416 │ ├── api # Folder containing API-related logic.
409417 │ │ ├── __init__.py
410418 │ │ ├── dependencies.py # Defines dependencies that can be reused across the API endpoints.
411419 │ │ ├── exceptions.py # Contains custom exceptions for the API.
420+ │ │ │
412421 │ │ └── v1 # Version 1 of the API.
413422 │ │ ├── __init__.py
414423 │ │ ├── login.py # API routes related to user login.
@@ -431,37 +440,38 @@ First, you may want to take a look at the project structure and understand what
431440 │ │ ├── __init__.py
432441 │ │ ├── crud_base.py # Base CRUD operations class that can be extended by other CRUD modules.
433442 │ │ ├── crud_posts.py # CRUD operations for posts.
434- │ │ └── crud_users.py # CRUD operations for users.
443+ │ │ ├── crud_users.py # CRUD operations for users.
444+ │ │ └── helper.py # Helper functions for CRUD operations.
435445 │ │
436- │ ├── main.py # Entry point that imports and creates the FastAPI application instance.
437446 │ ├── models # ORM models for the application.
438447 │ │ ├── __init__.py
439448 │ │ ├── post.py # ORM model for posts.
440449 │ │ └── user.py # ORM model for users.
441450 │ │
442- │ ├── schemas # Pydantic schemas for data validation.
443- │ │ ├── __init__.py
444- │ │ ├── job.py # Schemas related to background jobs.
445- │ │ ├── post.py # Schemas related to posts.
446- │ │ └── user.py # Schemas related to users.
447- │ │
448- │ └── worker.py # Worker script for handling background tasks.
451+ │ └── schemas # Pydantic schemas for data validation.
452+ │ ├── __init__.py
453+ │ ├── job.py # Schemas related to background jobs.
454+ │ ├── post.py # Schemas related to posts.
455+ │ └── user.py # Schemas related to users.
449456 │
450457 ├── migrations # Directory for Alembic migrations.
451458 │ ├── README # General info and guidelines for migrations.
452459 │ ├── env.py # Environment configurations for Alembic.
453460 │ ├── script.py.mako # Template script for migration generation.
461+ │ │
454462 │ └── versions # Folder containing individual migration scripts.
463+ │ └── README.MD
455464 │
456- ├── pyproject.toml # Configuration file for Poetry, lists project dependencies.
457465 ├── scripts # Utility scripts for the project.
466+ │ ├── __init__.py
458467 │ └── create_first_superuser.py # Script to create the first superuser in the application.
459468 │
460469 └── tests # Directory containing all the tests.
461470 ├── __init__.py # Initialization file for the tests package.
462471 ├── conftest.py # Configuration and fixtures for pytest.
463472 ├── helper.py # Helper functions for writing tests.
464473 └── test_user.py # Tests related to the user model and endpoints.
474+
465475```
466476
467477### 5.2 Database Model
@@ -552,6 +562,76 @@ CRUDEntity = CRUDBase[Entity, EntityCreateInternal, EntityUpdate, EntityUpdateIn
552562crud_entity = CRUDEntity(Entity)
553563```
554564
565+ When actually using the crud in an endpoint, to get data you just pass the database connection and the attributes as kwargs:
566+ ``` python
567+ # Here I'm getting the users with email == user.email
568+ user = await crud_users.get(db = db, email = user.email)
569+ ```
570+
571+ To get a list of objects with the attributes, you should use the get_multi:
572+ ``` python
573+ # Here I'm getting 100 users with the name David except for the first 3
574+ user = await crud_users.get_multi(
575+ db = db,
576+ offset = 3 ,
577+ limit = 100 ,
578+ name = " David"
579+ )
580+ ```
581+
582+ To create, you pass a ` CreateSchemaType ` object with the attributes, such as a ` CreateUser ` pydantic schema:
583+ ``` python
584+ from app.core.schemas.user import UserCreate
585+
586+ # Creating the object
587+ user_internal = UserCreate(
588+ name = " user" ,
589+ username = " myusername" ,
590+ 591+ )
592+
593+ # Passing the object to be created
594+ crud_users.create(db = db, object = user_internal)
595+ ```
596+
597+ To just check if there is at least one row that matches a certain set of attributes, you should use ` exists `
598+ ``` python
599+ # This queries only the email variable, and returns True if there's at least one or False if there is none
600+ crud_users.exists(db = db, email = user@ example.com)
601+ ```
602+
603+ To update you pass an ` object ` which may be a ` pydantic schema ` or just a regular ` dict ` , and the kwargs.
604+ You will update with ` objects ` the rows that match your ` kwargs ` .
605+ ``` python
606+ # Here I'm updating the user with username == "myusername". I'll change his name to "Updated Name"
607+ crud_users.update(db = db, object = {name=" Updated Name" }, username = " myusername" )
608+ ```
609+
610+ To delete we have two options:
611+ - db_delete: actually deletes the row from the database
612+ - delete:
613+ - adds ` "is_deleted": True ` and ` deleted_at: datetime.utcnow() ` if the model inherits from ` PersistentDeletion ` (performs a soft delete), but keeps the object in the database.
614+ - actually deletes the row from the database if the model does not inherit from ` PersistentDeletion `
615+
616+ ``` python
617+ # Here I'll just change is_deleted to True
618+ crud_users.delete(db = db, username = " myusername" )
619+
620+ # Here I actually delete it from the database
621+ crud_users.db_delete(db = db, username = " myusername" )
622+ ```
623+
624+ #### Advanced - Efficient Get
625+ For the ` get ` and ` get_multi ` methods we have the option to define a ` schema_to_select ` attribute, which is what actually makes the queries more efficient. When you pass a pydantic schema in ` schema_to_select ` to the ` get ` or ` get_multi ` methods, only the attributes in the schema will be selected.
626+ ``` python
627+ from app.schemas.user import UserRead
628+ # Here it's selecting all of the user's data, but maybe I just need what I'll return, the UserRead
629+ crud_user.get(db = db, username = " myusername" )
630+
631+ # Now it's only selecting the data that is in UserRead. Since that's my response_model, it's all I need
632+ crud_user.get(db = db, username = " myusername" , schema_to_select = UserRead)
633+ ```
634+
555635### 5.7 Routes
556636Inside ` app/api/v1 ` , create a new ` entities.py ` file and create the desired routes
557637``` python
0 commit comments