# 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.Meta` class for model configuration - Easily convert your query results to `pydantic` models via `Model.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: - http://localhost:8000/docs **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`: ```python 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`: ```python 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 [ ] # 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 [ ] # 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`: ```python 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} ```