Releases: benavlabs/FastAPI-boilerplate
0.14.0
Benav Labs FastAPI boilerplate
Yet another template to speed your FastAPI development up, now with proper docs and an admin panel.
What's Changed
- warning plus import for db migrations by @igorbenav in #140
- Update ARQ Job Queues documentation and add database session by @leonardovida in #141
- Fixes default expire time in creating access token by @KennethTV in #143
- Fixes by @igorbenav in #144
- enhance test setup by @arab0v in #148
- Update Dockerfile to install additional Poetry plugin by @sujithkupen in #154
- rate limiter changed from module to class by @igorbenav in #158
- blacklist both tokens for logout by @igorbenav in #159
- fastcrud bump, dependencies fixed by @igorbenav in #160
- remove comments by @igorbenav in #161
- bug fix by @igorbenav in #163
- bugfix: syntax error by @LongDinhh in #164
- Replace hardcoded localhost with POSTGRES_SERVER env var. by @epinapala in #166
- Dynamically importing app models by @geekashu in #167
- Tied the version of Python to 3.11 to fix Greenlet compatibility by @Harry-Tom in #174
- Updated the SECRET_KEY config item to use the SecretStr class by @Harry-Tom in #173
- added unused create_tables function to lifespan_factory by @oliwertrzeciak in #172
- Update env.py by @naaive in #171
- add banner by @igorbenav in #175
- Migrate to UV, Workflows, Bump Gunicorn by @igorbenav in #176
- initial documentation by @igorbenav in #177
- Add warning to docs, fix url by @igorbenav in #178
- add CRUDAdmin for admin panel by @igorbenav in #180
New Contributors
- @leonardovida made their first contribution in #141
- @KennethTV made their first contribution in #143
- @arab0v made their first contribution in #148
- @sujithkupen made their first contribution in #154
- @LongDinhh made their first contribution in #164
- @epinapala made their first contribution in #166
- @geekashu made their first contribution in #167
- @Harry-Tom made their first contribution in #174
- @oliwertrzeciak made their first contribution in #172
- @naaive made their first contribution in #171
Full Changelog: v0.13.0...v0.14.0
📖 Documentation
📚 Visit our comprehensive documentation at benavlabs.github.io/FastAPI-boilerplate
⚠️ Documentation StatusThis is our first version of the documentation. While functional, we acknowledge it's rough around the edges - there's a huge amount to document and we needed to start somewhere! We built this foundation (with a lot of AI assistance) so we can improve upon it.
Better documentation, examples, and guides are actively being developed. Contributions and feedback are greatly appreciated!
This README provides a quick reference for LLMs and developers, but the full documentation contains detailed guides, examples, and best practices.
0. About
FastAPI boilerplate creates an extendable async API using FastAPI, Pydantic V2, SQLAlchemy 2.0 and PostgreSQL:
FastAPI
: modern Python web framework for building APIsPydantic V2
: the most widely used data Python validation library, rewritten in Rust(5x-50x faster)
SQLAlchemy 2.0
: Python SQL toolkit and Object Relational MapperPostgreSQL
: The World's Most Advanced Open Source Relational DatabaseRedis
: Open source, in-memory data store used by millions as a cache, message broker and more.ARQ
Job queues and RPC in python with asyncio and redis.Docker Compose
With a single command, create and start all the services from your configuration.NGINX
High-performance low resource consumption web server used for Reverse Proxy and Load Balancing.
Tip
There's a SQLModel
version as well, but it's no longer updated: SQLModel-boilerplate.
1. Features
- ⚡️ Fully async
- 🚀 Pydantic V2 and SQLAlchemy 2.0
- 🔐 User authentication with JWT
- 🍪 Cookie based refresh token
- 🏬 Easy redis caching
- 👜 Easy client-side caching
- 🚦 ARQ integration for task queue
- ⚙️ Efficient and robust queries with fastcrud
- ⎘ Out of the box offset and cursor pagination support with fastcrud
- 🛑 Rate Limiter dependency
- 👮 FastAPI docs behind authentication and hidden based on the environment
- 🔧 Modern and light admin interface powered by CRUDAdmin
- 🚚 Easy running with docker compose
- ⚖️ NGINX Reverse Proxy and Load Balancing
2. Contents
0.13.0
0.13.0 Summary
🚀Features
- SQLModel version of boilerplate added 🎉
- fastcrud paginated added
🔎Bug fixes
- minor mypy and ruff fixes
- gunicorn bumped, security issue fixed
- fastcrud bumped to 0.12.0 with bug fixes
What's Changed
- README.md broken link fix by @igorbenav in #122
- Fastcrud paginated by @igorbenav in #123
- minor mypy and ruff fixes, fastcrud bumped to 0.10.0 by @igorbenav in #128
- bump fastcrud to 0.11.0 by @igorbenav in #129
- Update README.md by @igorbenav in #131
- Update README.md by @igorbenav in #133
- gunicorn bumped by @igorbenav in #134
- fastcrud bumped to 0.12.0 with bug fixes by @igorbenav in #135
- Update README.md by @igorbenav in #136
- SQLModel version link added by @igorbenav in #137
Full Changelog: v0.12.4...v0.13.0
0.12.4
0.12.4 Summary
🚀Features
- improved scripts logging
🔎Bug fixes
- remove
db.commit()
from async_get_db - thanks @mithun2003 - using fastcrud, result from get is no longer a db_row object, so no longer passing it in delete
What's Changed
- logging added to scripts, get_db fix, endpoints fixed for fastcrud usage by @igorbenav in #121
Full Changelog: v0.12.3...v0.12.4
0.12.3
0.12.3
🔎Bug fixes
- docs not generated bug fix #118 by @luca-medeiros
- spelling fix #115 by @rememberlenny
What's Changed
- Fix default.conf spelling by @rememberlenny in #115
- bug: fix missing router when creating application by @luca-medeiros in #118
New Contributors
- @rememberlenny made their first contribution in #115
Full Changelog: v0.12.2...v0.12.3
0.12.2
0.12.2
⚡️Enhancements
- now using recommended lifespan events instead of startup and shutdown events
- libs bumped
🔎Bug fixes
- wrong .env reference in docker-compose fixed
What's Changed
- Lifespan Events, Libs bumped, .env fix by @igorbenav in #114
- fastcrud bumped to 0.6.0 by @igorbenav in #116
Full Changelog: v0.11.1...v0.12.2
0.11.1
0.11.1
🔎Bug fixes
Warning
Content-Type Header ReDoS - FastAPI vulnerability fixed
Update python-multipart to 0.0.7 as soon as possible.
https://github.com/tiangolo/fastapi/security/advisories/GHSA-qf9m-vfgh-m389
What's Changed
- upgrade python multipart, fastapi, fastcrud by @igorbenav in #112
Full Changelog: v0.11.0...v0.11.1
0.11.0
0.11.0 Summary
🚀Features
- replaced CRUDBase with fastcrud for more robust operations
- worker script refactored, thanks @AlessioBugetti
- print statements removed, thanks @shreyasSarve
- PGAdmin container for PostgreSQL administration and debugging, thanks @gmirsky
create_tables_on_start
parameter added in setup functionruff
added aspre-commit
, thanks @luca-medeiros
📝Docs
- all docs updated to reflect changes
- pull request template added
- Contributing moved to its own file and enhanced
- Issue template added
- Code of conduct added
1. fastcrud
Set Up FastAPI and FastCRUD
from fastapi import FastAPI
from fastcrud import FastCRUD, crud_router
from sqlalchemy.ext.asyncio import AsyncSession, create_async_engine
from sqlalchemy.orm import sessionmaker
# Database setup (Async SQLAlchemy)
DATABASE_URL = "sqlite+aiosqlite:///./test.db"
engine = create_async_engine(DATABASE_URL, echo=True)
async_session = sessionmaker(engine, class_=AsyncSession, expire_on_commit=False)
# FastAPI app
app = FastAPI()
# CRUD operations setup
crud = FastCRUD(Item)
# CRUD router setup
item_router = crud_router(
session=async_session,
model=Item,
crud=crud,
create_schema=ItemCreateSchema,
update_schema=ItemUpdateSchema,
path="/items",
tags=["Items"]
)
app.include_router(item_router)
Using FastCRUD in User-Defined FastAPI Endpoints
For more control over your endpoints, you can use FastCRUD directly within your custom FastAPI route functions. Here's an example:
Usage:
from fastapi import FastAPI, Depends, HTTPException
from sqlalchemy.ext.asyncio import AsyncSession
from fastcrud import FastCRUD
from yourapp.models import Item
from yourapp.schemas import ItemCreateSchema, ItemUpdateSchema
app = FastAPI()
# Assume async_session is already set up as per the previous example
# Instantiate FastCRUD with your model
item_crud = FastCRUD(Item)
@app.post("/custom/items/")
async def create_item(item_data: ItemCreateSchema, db: AsyncSession = Depends(async_session)):
return await item_crud.create(db, item_data)
@app.get("/custom/items/{item_id}")
async def read_item(item_id: int, db: AsyncSession = Depends(async_session)):
item = await item_crud.get(db, id=item_id)
if not item:
raise HTTPException(status_code=404, detail="Item not found")
return item
# You can add more routes for update and delete operations in a similar fashion
To know all available methods, check it in fastcrud readme.
2. create_tables_on_start
If you want to stop tables from being created every time you run the api, you should disable this here:
# app/main.py
from .api import router
from .core.config import settings
from .core.setup import create_application
# create_tables_on_start defaults to True
app = create_application(router=router, settings=settings, create_tables_on_start=False)
🔎Bug fixes
- pyproject.toml fixed, thanks @DmitryIo
- get task endpoint bug fixed
- deprecated typing classes replaced, thanks @eredden
What's Changed
- Add ruff linter by @luca-medeiros in #83
- Added the comment and in the docs to change docker-compose.yml for migrations by @igorbenav in #85
- create_tables_on_start created, docs added by @igorbenav in #86
- Add PGAdmin container for PostgreSQL administration and debugging by @gmirsky in #75
- Removed deprecated typing classes and replaced with native Python dict, list, type, etc. by @eredden in #90
- add pre-commit configs by @luca-medeiros in #92
- Remove all print statements #93 by @shreyasSarve in #95
- Move worker script by @AlessioBugetti in #97
- Fix for get task endpoint bug by @igorbenav in #99
- Fix of pyproject.toml by @DmitryIo in #101
- Create CODE_OF_CONDUCT.md by @igorbenav in #102
- Update issue templates by @igorbenav in #103
- Create CONTRIBUTING.md by @igorbenav in #104
- Update CONTRIBUTING.md by @igorbenav in #105
- Create PULL_REQUEST_TEMPLATE.md by @igorbenav in #106
- Update README.md by @igorbenav in #107
- Fast crud by @igorbenav in #109
- Update README.md by @igorbenav in #110
New Contributors
- @gmirsky made their first contribution in #75
- @eredden made their first contribution in #90
- @shreyasSarve made their first contribution in #95
- @AlessioBugetti made their first contribution in #97
- @DmitryIo made their first contribution in #101
Full Changelog: v0.10.0...v0.11.0
0.10.0
0.10.0 Summary
🚀Features
datetime
refactored to be timezone aware #79 #82 (thanks @mithun2003)passlib
replaced withbcrypt
for password hashing #74- pydantic
validator
moved to v2field_Validator
#72 - config port data type consistency #69 (thanks @luca-medeiros)
- pyproject.toml moved to the root folder #65
- Tests folder moved to core, imports changed to relative imports #65
📝Docs
- Now there's the option to use a template for
.env
,docker-compose.yml
andDockerfile
:
Tip
If you are in a hurry, you may use one of the following templates (containing a .env
, docker-compose.yml
and Dockerfile
):
- Running locally with uvicorn
- Runing in staging with gunicorn managing uvicorn workers
- Running in production with NGINX
Warning
Do not forget to place docker-compose.yml
and Dockerfile
in the root
folder, while .env
should be in the src
folder.
- Docs to run with NGINX were revised and are clearer now
🔎Bug fixes
- CRUDBase count method fixed when kwargs is none #81
- pydantic
allow_reuse
removed #70 - pagination bug fixed #66
- mypy multiple type hint fixes
What's Changed
- Update README.md by @igorbenav in #64
- Folder structure by @igorbenav in #65
- pagination bug fixed by @igorbenav in #66
- config.py port datatype consistency by @luca-medeiros in #69
- pydantic allow_reuse removed, one less warning for tests by @igorbenav in #70
- commented non essential services in docker compose by @igorbenav in #71
- pydantic validators migrated to v2 by @igorbenav in #72
- added return type hint to rate limit validator by @igorbenav in #73
- passlib replaced with bcrypt for password hashing by @igorbenav in #74
- Update README.md by @igorbenav in #77
- Update README.md by @igorbenav in #78
- CRUDBase count method bug fix by @igorbenav in #81
- Refactor datetime.utcnow() to datetime.now(timezone.utc) by @mithun2003 in #80
- 79 datetimeutcnow is deprecated as of python 312 by @igorbenav in #82
New Contributors🎉
- @luca-medeiros made their first contribution in #69
- @mithun2003 made their first contribution in #80
Full Changelog: v0.9.0...v0.10.0
0.9.0
0.9.0 Summary
🚀Features
- JWT Authentication now supports refresh token🎉
📝Docs
🔐JWT Authentication With Refresh Token
The JWT in the boilerplate was updated to work in the following way:
- JWT Access Tokens: how you actually access protected resources is passing this token in the request header.
- Refresh Tokens: you use this type of token to get an
access token
, which you'll use to access protected resources.
The access token
is short lived (default 30 minutes) to reduce the damage of a potential leak. The refresh token
, on the other hand, is long lived (default 7 days), and you use it to renew your access token
without the need to provide username and password every time it expires.
Since the refresh token
lasts for a longer time, it's stored as a cookie in a secure way:
# app/api/v1/login
...
response.set_cookie(
key="refresh_token",
value=refresh_token,
httponly=True, # Prevent access through JavaScript
secure=True, # Ensure cookie is sent over HTTPS only
samesite='Lax', # Default to Lax for reasonable balance between security and usability
max_age=<number_of_seconds> # Set a max age for the cookie
)
...
You may change it to suit your needs. The possible options for samesite
are:
Lax
: Cookies will be sent in top-level navigations (like clicking on a link to go to another site), but not in API requests or images loaded from other sites.Strict
: Cookies will be sent in top-level navigations (like clicking on a link to go to another site), but not in API requests or images loaded from other sites.None
: Cookies will be sent with both same-site and cross-site requests.
🚀Usage
What you should do with the client is:
Login
: Send credentials to/api/v1/login
. Store the returned access token in memory for subsequent requests.Accessing Protected Routes
: Include the access token in the Authorization header.Token Renewal
: On access token expiry, the front end should automatically call/api/v1/refresh
for a new token.Login Again
: If refresh token is expired, credentials should be sent to/api/v1/login
again, storing the new access token in memory.Logout
: Call /api/v1/logout to end the session securely.
This authentication setup in the provides a robust, secure, and user-friendly way to handle user sessions in your API applications.
What's Changed
- Token refresh by @igorbenav in #63
Full Changelog: v0.8.3...v0.9.0
0.8.3
0.8.3 Summary
- Docker Compose improved
- docs for running with docker compose improved
🔎Bug fixes
- Expose used now in docker compose
- Docs fixed to use the boilerplate with docker compose
What's Changed
- Some corrections and improvements to run with docker compose by @YuriiMotov in #62
New Contributors
- 🚀Special thanks to @YuriiMotov for the fixes in #62
Full Changelog: v0.8.2...v0.8.3