11# FastAPI-boilerplate
22> A template to speed your FastAPI development up.
33
4- ## About
4+ ## 0. About
55** FastAPI boilerplate** creates an extendable async API using FastAPI, Pydantic V2, SQLAlchemy 2.0 and PostgreSQL:
66- [ ` FastAPI ` ] ( https://fastapi.tiangolo.com ) : modern Python web framework for building APIs
7- - [ ` Pydantic V2 ` ] ( https://docs.pydantic.dev/2.4/ ) : the most widely used data validation library for Python now rewritten in Rust [ ` (5x to 50x speed improvement) ` ] ( https://docs.pydantic.dev/latest/blog/pydantic-v2-alpha/ )
7+ - [ ` Pydantic V2 ` ] ( https://docs.pydantic.dev/2.4/ ) : the most widely used data validation library for Python, now rewritten in Rust [ ` (5x to 50x speed improvement) ` ] ( https://docs.pydantic.dev/latest/blog/pydantic-v2-alpha/ )
88- [ ` SQLAlchemy 2.0 ` ] ( https://docs.sqlalchemy.org/en/20/changelog/whatsnew_20.html ) : Python SQL toolkit and Object Relational Mapper
99- [ ` PostgreSQL ` ] ( https://www.postgresql.org ) : The World's Most Advanced Open Source Relational Database
1010
11- ## Features
11+ ## 1. Features
1212 - Fully async
1313 - Pydantic V2 and SQLAlchemy 2.0
1414 - User authentication with JWT
1515 - Easily extendable
1616 - Flexible
1717
18+ ### 1.1 To do
19+ - [ ] Redis cache
20+ - [ ] Google SSO
21+ - [ ] Arq job queues
22+
23+ ## 2. Contents
24+ 0 . [ About] ( #0-about )
25+ 1 . [ Features] ( #1-features )
26+ 1 . [ To do] ( #11-to-do )
27+ 2 . [ Contents] ( #2-contents )
28+ 3 . [ Usage] ( #3-usage )
29+ 4 . [ Requirements] ( #4-requirements )
30+ 1 . [ Packages] ( #41-packages )
31+ 2 . [ Environment Variables] ( #42-environment-variables )
32+ 5 . [ Running PostgreSQL with docker] ( #5-running-postgresql-with-docker )
33+ 6 . [ Running the api] ( #6-running-the-api )
34+ 7 . [ Creating the first superuser] ( #7-creating-the-first-superuser )
35+ 8 . [ Database Migrations] ( #8-database-migrations )
36+ 9 . [ Extending] ( #9-extending )
37+ 1 . [ Database Model] ( #91-database-model )
38+ 2 . [ SQLAlchemy Models] ( #92-sqlalchemy-model )
39+ 3 . [ Pydantic Schemas] ( #93-pydantic-schemas )
40+ 4 . [ Alembic Migrations] ( #94-alembic-migration )
41+ 5 . [ CRUD] ( #95-crud )
42+ 6 . [ Routes] ( #96-routes )
43+ 7 . [ Running] ( #97-running )
44+ 10 . [ Testing] ( #10-testing )
45+ 11 . [ Contributing] ( #11-contributing )
46+ 12 . [ References] ( #12-references )
47+ 13 . [ License] ( #13-license )
48+ 14 . [ Contact] ( #14-contact )
49+
1850___
19- # Usage
20- ## Start by cloning the repository
51+ ## 3. Usage
52+ Start by cloning the repository
2153``` sh
2254git clone https://github.com/igormagalhaesr/FastAPI-boilerplate
2355```
2456___
25- ## Requirements
26- ### Packages
57+ ## 4. Requirements
58+ ### 4.1 Packages
2759Then install poetry:
2860``` sh
2961pip install poetry
@@ -34,7 +66,7 @@ In the **src** directory, run to install required packages:
3466poetry install
3567```
3668
37- ### Environment Variables
69+ ### 4.2 Environment Variables
3870Then create a .env file:
3971``` sh
4072touch .env
@@ -85,7 +117,7 @@ ADMIN_PASSWORD="your_password"
85117```
86118
87119___
88- ## Running PostgreSQL with docker:
120+ ## 5. Running PostgreSQL with docker:
89121Install docker if you don't have it yet, then run:
90122``` sh
91123docker pull postgres
@@ -114,24 +146,24 @@ docker run -d \
114146[ ` If you didn't create the .env variables yet, click here. ` ] ( #environment-variables )
115147
116148___
117- ## Running the api
149+ ## 6. Running the api
118150While in the ** src** folder, run to start the application with uvicorn server:
119151``` sh
120152poetry run uvicorn app.main:app --reload
121153```
122154
123155___
124- ## Creating the first superuser:
156+ ## 7. Creating the first superuser:
125157While in the ** src** folder, run (after you started the application at least once to create the tables):
126158``` sh
127159poetry run python -m scripts.create_first_superuser
128160```
129161
130162___
131- ## Database Migrations
163+ ## 8. Database Migrations
132164Migrations done via [ Alembic] ( https://alembic.sqlalchemy.org/en/latest/ ) :
133165
134- Whenever you change somethin in the database, in the ** src** directory, run to create the script:
166+ Whenever you change something in the database, in the ** src** directory, run to create the script:
135167``` sh
136168poetry run alembic revision --autogenerate
137169```
@@ -142,7 +174,130 @@ poetry run alembic upgrade head
142174```
143175
144176___
145- ## Testing
177+ ## 9. Extending
178+ ### 9.1 Database Model
179+ Create the new entities and relationships and add them to the model
180+ ![ diagram] ( https://user-images.githubusercontent.com/43156212/274053323-31bbdb41-15bf-45f2-8c8e-0b04b71c5b0b.png )
181+
182+ ### 9.2 SQLAlchemy Model
183+ Inside ** app/models** , create a new ** entity.py** for each new entity (replacing entity with the name) and define the attributes according to [ SQLAlchemy 2.0 standards] ( https://docs.sqlalchemy.org/en/20/orm/mapping_styles.html#orm-mapping-styles ) :
184+ ``` python
185+ from sqlalchemy import String, DateTime
186+ from sqlalchemy.orm import Mapped, mapped_column, relationship
187+
188+ from app.core.database import Base
189+
190+ class Entity (Base ):
191+ __tablename__ = " entity"
192+
193+ id : Mapped[int ] = mapped_column(
194+ " id" , autoincrement = True , nullable = False , unique = True , primary_key = True , init = False
195+ )
196+ name: Mapped[str ] = mapped_column(String(30 ))
197+ ...
198+ ```
199+
200+ ### 9.3 Pydantic Schemas
201+ Inside app/schemas, create a new entity.py for for each new entity (replacing entity with the name) and create the schemas according to [ Pydantic V2] ( https://docs.pydantic.dev/latest/#pydantic-examples ) standards:
202+ ``` python
203+ from typing import Annotated
204+
205+ from pydantic import BaseModel, EmailStr, Field, HttpUrl, ConfigDict
206+
207+ class EntityBase (BaseModel ):
208+ name: Annotated[
209+ str ,
210+ Field(min_length = 2 , max_length = 30 , examples = [" Entity Name" ])
211+ ...
212+ ]
213+
214+ class Entity (EntityBase ):
215+ ...
216+
217+ class EntityRead (EntityBase ):
218+ ...
219+
220+ class EntityCreate (EntityBase ):
221+ ...
222+
223+ class EntityCreateInternal (EntityCreate ):
224+ ...
225+
226+ class EntityUpdate (BaseModel ):
227+ ...
228+
229+ class EntityUpdateInternal (BaseModel ):
230+ ...
231+
232+ class EntityDelete (BaseModel ):
233+ model_config = ConfigDict(extra = ' forbid' )
234+
235+ is_deleted: bool
236+ deleted_at: datetime
237+
238+ ```
239+
240+ ### 9.4 Alembic Migration
241+ Then, while in the ** src** folder, run Alembic migrations:
242+ ``` sh
243+ poetry run alembic revision --autogenerate
244+ ```
245+
246+ And to apply the migration
247+ ``` sh
248+ poetry run alembic upgrade head
249+ ```
250+
251+ ### 9.5 CRUD
252+ Inside ** app/crud** , create a new crud_entities.py inheriting from CRUDBase for each new entity:
253+ ``` python
254+ from app.crud.crud_base import CRUDBase
255+ from app.models.entity import Entity
256+ from app.schemas.entity import EntityCreateInternal, EntityUpdate, EntityUpdateInternal, EntityDelete
257+
258+ CRUDEntity = CRUDBase[Entity, EntityCreateInternal, EntityUpdate, EntityUpdateInternal, EntityDelete]
259+ crud_entity = CRUDEntity(Entity)
260+ ```
261+
262+ ### 9.6 Routes
263+ Inside ** app/api/v1** , create a new entities.py file and create the desired routes
264+ ``` python
265+ from typing import Annotated
266+
267+ from fastapi import Depends
268+
269+ from app.schemas.entity import EntityRead
270+ from app.core.database import async_get_db
271+ ...
272+
273+ router = fastapi.APIRouter(tags = [" entities" ])
274+
275+ @router.get (" /entities" , response_model = List[EntityRead])
276+ async def read_entities (db : Annotated[AsyncSession, Depends(async_get_db)]):
277+ entities = await crud_entities.get_multi(db = db)
278+ return entities
279+
280+ ...
281+ ```
282+ Then in ** app/api/v1/__ init__ .py** add the router such as:
283+ ``` python
284+ from fastapi import APIRouter
285+ from app.api.v1.entity import router as entity_router
286+ ...
287+
288+ router = APIRouter(prefix = " /v1" ) # this should be there already
289+ ...
290+ router.include_router(entity_router)
291+ ```
292+
293+ ### 9.7 Running
294+ While in the ** src** folder, run to start the application with uvicorn server:
295+ ``` sh
296+ poetry run uvicorn app.main:app --reload
297+ ```
298+
299+ ___
300+ ## 10. Testing
146301For tests, create in .env:
147302```
148303# ------------- test -------------
@@ -152,7 +307,7 @@ TEST_USERNAME="testeruser"
152307TEST_PASSWORD="Str1ng$t"
153308```
154309
155- While in the tests folder, create your test file with the name "test_ {object }.py", replacing object with what you're testing
310+ While in the tests folder, create your test file with the name "test_ {entity }.py", replacing entity with what you're testing
156311``` sh
157312touch test_items.py
158313```
@@ -162,24 +317,24 @@ Finally create your tests (you may want to copy the structure in test_user.py),
162317poetry run python -m pytest
163318```
164319___
165- # Other stuff
166- ## Contributing
320+ ## 11. Contributing
321+ Contributions are appreciated, even if just reporting bugs, documenting stuff or answering questions. To contribute with a feature:
1673221 . Fork it (https://github.com/igormagalhaesr/FastAPI-boilerplate )
1683232 . Create your feature branch (` git checkout -b feature/fooBar ` )
1693243 . Test your changes while in the src folder ` poetry run python -m pytest `
1703254 . Commit your changes (` git commit -am 'Add some fooBar' ` )
1713265 . Push to the branch (` git push origin feature/fooBar ` )
1723276 . Create a new Pull Request
173328
174- ## References
329+ ## 12. References
175330This project was inspired by a few projects, it's based on them with things changed to the way I like (and pydantic, sqlalchemy updated)
176331* [ ` Full Stack FastAPI and PostgreSQL ` ] ( https://github.com/tiangolo/full-stack-fastapi-postgresql ) by @tiangolo himself
177332* [ ` FastAPI Microservices ` ] ( https://github.com/Kludex/fastapi-microservices ) by @kludex which heavily inspired this boilerplate
178- * [ Async Web API with FastAPI + SQLAlchemy 2.0] ( https://github.com/rhoboro/async-fastapi-sqlalchemy )
333+ * [ ` Async Web API with FastAPI + SQLAlchemy 2.0 ` ] ( https://github.com/rhoboro/async-fastapi-sqlalchemy )
179334
180- ## License
335+ ## 13. License
181336[ ` MIT ` ] ( LICENSE.md )
182337
183- ## Contact
338+ ## 14. Contact
184339Igor Magalhaes –
[ @igormagalhaesr ] ( https://twitter.com/igormagalhaesr ) –
[email protected] 185- [ github.com/igormagalhaesr] ( https://github.com/igormagalhaesr/ )
340+ [ github.com/igormagalhaesr] ( https://github.com/igormagalhaesr/ )
0 commit comments