| src/ohmyapi | ||
| tests | ||
| .gitignore | ||
| poetry.lock | ||
| pyproject.toml | ||
| README.md | ||
OhMyAPI
Think: Micro-Django, but API-first, less clunky and 100% async.
OhMyAPI is a Django-flavored web-application scaffolding framework and management layer. Built around FastAPI and TortoiseORM, it is 100% async.
It is blazingly fast, fun to use and comes with batteries included!
Features
- Django-like project-layout and -structure
- Django-like prject-level settings.py
- Django-like models via TortoiseORM
- Django-like
Model.Metaclass for model configuration - Easily convert your query results to
pydanticmodels viaModel.Schema - Django-like migrations (makemigrations & migrate) via Aerich
- Django-like CLI tooling (
startproject,startapp,shell,serve, etc) - Various optional builtin apps you can hook into your project
- Highly configurable and customizable
- 100% async
Getting started
Creating a Project
pip install ohmyapi
ohmyapi startproject myproject
cd myproject
This will create the following directory structure:
myproject/
- pyproject.toml
- README.md
- settings.py
Run your project with:
ohmyapi serve
In your browser go to:
Creating an App
Create a new app by:
ohmyapi startapp myapp
This will create the following directory structure:
myproject/
- myapp/
- __init__.py
- models.py
- routes.py
- pyproject.toml
- README.md
- settings.py
Add 'myapp' to your INSTALLED_APPS in settings.py.
Models
Write your first model in myapp/models.py:
from ohmyapi.db import Model, field
class Person(Model):
id: int = field.IntField(min=1, pk=True)
name: str = field.CharField(min_length=1, max_length=255)
username: str = field.CharField(min_length=1, max_length=255, unique=True)
age: int = field.IntField(min=0)
API Routes
Next, create your endpoints in myapp/routes.py:
from ohmyapi.router import APIRouter, HTTPException
from ohmyapi.db.exceptions import DoesNotExist
from .models import Person
router = APIRouter(prefix="/myapp")
@router.get("/")
async def list():
queryset = await Person.all()
return await Person.Schema.many.from_queryset(queryset)
@router.get("/:id")
async def get(id: int):
try:
queryset = await Person.get(pk=id)
return await Person.Schema.one(queryset)
except DoesNotExist:
raise HTTPException(status_code=404, detail="item not found")
...
Migrations
Before we can run the app, we need to create and initialize the database.
Similar to Django, first run:
ohmyapi makemigrations [ <app> ] # no app means all INSTALLED_APPS
This will create a migrations/ folder in you project root.
myproject/
- myapp/
- __init__.py
- models.py
- routes.py
- migrations/
- myapp/
- pyproject.toml
- README.md
- settings.py
Apply your migrations via:
ohmyapi migrate [ <app> ] # no app means all INSTALLED_APPS
Run your project:
ohmyapi serve
Shell
Similar to Django, you can attach to an interactive shell with your project already loaded inside.
ohmyapi shell
Authentication
A builtin auth app is available.
Simply add ohmyapi_auth to your INSTALLED_APPS and define a JWT_SECRET in your settings.py.
Remember to makemigrations and migrate for the necessary tables to be created in the database.
settings.py:
INSTALLED_APPS = [
'ohmyapi_auth',
...
]
JWT_SECRET = "t0ps3cr3t"
After restarting your project you will have access to the ohmyapi_auth app.
It comes with a User and Group model, as well as endpoints for JWT auth.
Create a super-user:
ohmyapi createsuperuser
Permissions
API-Level
Use FastAPI's Depends pattern to implement API-level access-control.
In your routes.py:
from ohmyapi.router import APIRouter, Depends
from ohmyapi_auth.models import User
from ohmyapi_auth.permissions import require_authenticated
router = APIRouter(prefix="/myapp")
@router.get("/")
def must_be_authenticated(user: User = Depends(require_authenticated)):
return {"user": user}