Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/mfreeborn/fastapi-sqlalchemy
Adds simple SQLAlchemy support to FastAPI
https://github.com/mfreeborn/fastapi-sqlalchemy
Last synced: 13 days ago
JSON representation
Adds simple SQLAlchemy support to FastAPI
- Host: GitHub
- URL: https://github.com/mfreeborn/fastapi-sqlalchemy
- Owner: mfreeborn
- License: mit
- Created: 2019-11-03T16:30:26.000Z (about 5 years ago)
- Default Branch: master
- Last Pushed: 2024-04-09T04:47:10.000Z (7 months ago)
- Last Synced: 2024-10-01T11:43:14.430Z (about 1 month ago)
- Language: Python
- Size: 101 KB
- Stars: 611
- Watchers: 11
- Forks: 37
- Open Issues: 20
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
- awesome-fastapi - FastAPI SQLAlchemy - Simple integration between FastAPI and [SQLAlchemy](https://www.sqlalchemy.org/). (Third-Party Extensions / Databases)
- awesome-fastapi - FastAPI SQLAlchemy - Simple integration between FastAPI and [SQLAlchemy](https://www.sqlalchemy.org/). (Third-Party Extensions / Databases)
- jimsghstars - mfreeborn/fastapi-sqlalchemy - Adds simple SQLAlchemy support to FastAPI (Python)
- best-of-web-python - GitHub - 62% open · ⏱️ 09.04.2024): (FastAPI Utilities)
README
[![image](https://img.shields.io/pypi/v/FastAPI-SQLAlchemy?color=blue)](https://pypi.org/project/FastAPI-SQLAlchemy/)
FastAPI-SQLAlchemy provides a simple integration between
[FastAPI](https://github.com/tiangolo/fastapi) and
[SQLAlchemy](https://github.com/pallets/flask-sqlalchemy) in your
application. It gives access to useful helpers to facilitate the
completion of common tasks.# Installing
Install and update using
[pip](https://pip.pypa.io/en/stable/quickstart/):
``` text
$ pip install fastapi-sqlalchemy
```
# Examples
## Models definition
``` python
from sqlalchemy import Column, Integer, String, create_engine
from sqlalchemy.orm import DeclarativeMeta, declarative_base, sessionmakerfrom fastapi_sqlalchemy import SQLAlchemy
db = SQLAlchemy(url="sqlite:///example.db")
#Define User class
class User(db.Base):
__tablename__ = "items"id = Column(Integer, primary_key=True)
name = Column(String)
email = Column(String)def __repr__(self):
return f"User(id={self.id}, name='{self.name}',email='{self.email}')"
```
## Usage inside of a route
``` python
from fastapi import FastAPI
from models import User, db
from pydantic import BaseModelfrom fastapi_sqlalchemy import DBSessionMiddleware
app = FastAPI()
# Add SQLAlchemy session middleware to manage database sessions
app.add_middleware(DBSessionMiddleware, db=db)# Endpoint to retrieve all users
@app.get("/users")
def get_users():
"""
Retrieve a list of all users.Returns:
List[User]: A list of User objects.
"""
return User.query.all()# Pydantic model for creating new users
class UserCreate(BaseModel):
name: str
email: str# Endpoint to add a new user
@app.post("/add_user")
def add_user(user_data: UserCreate):
"""
Add a new user to the database.Args:
user_data (UserCreate): User data including name and email.Returns:
dict: A message indicating the success of the operation.
"""
user = User(**user_data.model_dump())
print(user)
user.save()
return {"message": "User created successfully"}```
You can initialize the SQLAlchemy() class similar to the way
flask-sqlalchemy, this allows for multiple database connections to work
at the same time.
## Usage outside of a routeSometimes it is useful to be able to access the database outside the
context of a request, such as in scheduled tasks which run in the
background:``` python
import pytz
from apscheduler.schedulers.asyncio import AsyncIOScheduler # other schedulers are available
from fastapi import FastAPI
from models import User, db
from fastapi_sqlalchemy import DBSessionMiddlewareapp = FastAPI()
app.add_middleware(DBSessionMiddleware, db_url="sqlite:///example.db")
@app.on_event('startup')
async def startup_event():
scheduler = AsyncIOScheduler(timezone=pytz.utc)
scheduler.start()
scheduler.add_job(count_users_task, "cron", hour=0) # runs every night at midnightdef count_users_task():
"""Count the number of users in the database and save it into the user_counts table."""# we are outside of a request context, therefore we cannot rely on ``DBSessionMiddleware``
# to create a database session for us. Instead, we can use the same ``db`` object and
# use it as a context manager, like so:with db():
user_count = User.query.count()user_count = UserCount(user_count)
user_count.save()# no longer able to access a database session once the db() context manager has ended
return users
```
## Custom Model Base
You can define custom BaseModels, or extend the built in ModelBase to provide extended shared functionality for you database models.
```python
import inspect
from typing import Listfrom sqlalchemy import Column
from fastapi_sqlalchemy import ModelBase
class BaseModel(ModelBase):
@classmethod
def new(cls, **kwargs):
obj = cls(**kwargs)
obj.save()
return obj@classmethod
def get(cls, **kwargs):
result: cls = cls.query.filter_by(**kwargs).first()
return result@classmethod
def get_all(cls, **kwargs):
result: List[cls] = cls.query.filter_by(**kwargs).all()
return resultdef update(self, **kwargs):
for column, value in kwargs.items():
setattr(self, column, value)self.save()
return self```
As you can see the above BaseModel class adds support for various common functions and operations.
## Complete examples- [Using single database](examples/single_db/)
- [Using multiple databases](examples/multi_db/)
- [Legacy method](examples/legacy/)
# Legacy Examples## Models definition
Note the only change that you need to make is to add the db.Base inheritance to each of your
model classes
``` python
from sqlalchemy import Column, Integer, String, create_engine
from sqlalchemy.orm import declarative_base, sessionmakerfrom fastapi_sqlalchemy import ModelBase, SQLAlchemy
db = SQLAlchemy(url="sqlite:///example.db")
# Define the User class representing the "users" database table
# Using the SQLAlchemy Base property instead of defining your own
# And inheriting from the BaseModel class for type hinting and helpful builtin methods and properties
class User(ModelBase, db.Base):
__tablename__ = "users"id = Column(Integer, primary_key=True)
name = Column(String)
email = Column(String)def __repr__(self):
return f"User(id={self.id}, name='{self.name}',email='{self.email}')"```
## Usage inside of a route``` python
from fastapi import FastAPI
from fastapi_sqlalchemy import DBSessionMiddleware # middleware helper
from fastapi_sqlalchemy import db # an object to provide global access to a database sessionfrom app.models import User
app = FastAPI()
app.add_middleware(DBSessionMiddleware, db_url="sqlite:///example.db")
# once the middleware is applied, any route can then access the database session
# from the global ``db``@app.get("/users")
def get_users():
users = db.session.query(User).all()return users
```Note that the session object provided by `db.session` is based on the
Python3.7+ `ContextVar`. This means that each session is linked to the
individual request context in which it was created.## Usage outside of a route
Sometimes it is useful to be able to access the database outside the
context of a request, such as in scheduled tasks which run in the
background:``` python
import pytz
from apscheduler.schedulers.asyncio import AsyncIOScheduler # other schedulers are available
from fastapi import FastAPI
from fastapi_sqlalchemy import dbfrom app.models import User, UserCount
app = FastAPI()
app.add_middleware(DBSessionMiddleware, db_url="sqlite:///example.db")
@app.on_event('startup')
async def startup_event():
scheduler = AsyncIOScheduler(timezone=pytz.utc)
scheduler.start()
scheduler.add_job(count_users_task, "cron", hour=0) # runs every night at midnightdef count_users_task():
"""Count the number of users in the database and save it into the user_counts table."""# we are outside of a request context, therefore we cannot rely on ``DBSessionMiddleware``
# to create a database session for us. Instead, we can use the same ``db`` object and
# use it as a context manager, like so:with db():
user_count = db.session.query(User).count()db.session.add(UserCount(user_count))
db.session.commit()# no longer able to access a database session once the db() context manager has ended
return users
```