A modular Python backend framework built on FastAPI
Project description
Axon Framework
A modular Python backend framework built on FastAPI. Inspired by NestJS and Laravel — modules, DI container, hook bus, scheduler, and a full CLI — without the boilerplate.
Install
pip install python-axon
Create a project
axon create_project myapp
cd myapp
pip install -r requirements.txt
./manage migrate
./manage runserver
Your API is live at http://localhost:8000. Docs at http://localhost:8000/docs.
Import surface
Everything a module builder needs comes from three places:
# Core classes and all helpers
from axon import Module, Service, Model, Router, Manifest, Context, Log
from axon import bind, make, override, extend, env, config, abort
# Database field types
from axon.fields import StringField, BoolField, IntField, ForeignKey, ChoiceField
# Auth guards for routes
from axon.auth import require_auth, require_role, optional_auth
# HTTP error responses
from axon.responses import not_found, bad_request, forbidden, unprocessable
Old deep imports (from axon.core.*) continue to work — nothing breaks.
Scaffold a module
./manage make:module orders
Generates app/modules/orders/ with models, services, routes, schemas, hooks, and a manifest — all wired and ready.
Module anatomy
# app/modules/orders/__init__.py
from axon import Module, bind, on, env, Log
class Module(Module):
@property
def name(self) -> str:
return "orders"
def register(self) -> None:
bind(OrderService) # bare bind() — same as self.bind()
async def boot(self) -> None:
on("platform.booted", self._ready)
async def _ready(self, payload: dict) -> None:
Log.i("orders", "module ready")
Model
# app/modules/orders/models.py
from axon import Model as AxonModel
from axon.fields import StringField, DecimalField, ChoiceField, ForeignKey
class Order(AxonModel):
status = ChoiceField(["pending", "paid", "shipped"], default="pending")
total = DecimalField(precision=10, scale=2)
user_id = ForeignKey("auth_users.id")
Service
# app/modules/orders/services.py
from axon import Service as AxonService, Log
class OrderService(AxonService):
def create(self, data: dict) -> dict:
with self.db().session() as s:
order = Order(**data)
s.add(order)
s.flush()
Log.i("OrderService", "created id=%d", order.id)
return order.to_dict()
Routes
# app/modules/orders/routes.py
from axon import Router
from axon.auth import require_auth
from axon.responses import not_found
from .services import OrderService
from .schemas import OrderIn
router = Router(prefix="/orders", tags=["orders"])
@router.get("/")
async def index(ctx, svc: OrderService):
return svc.list()
protected = router.group("", middleware=[require_auth])
@protected.post("/", status=201)
async def store(body: OrderIn, ctx, svc: OrderService):
return svc.create(body.model_dump())
Manifest
# app/modules/orders/manifest.py
from axon import Manifest
manifest = Manifest(
name = "orders",
version = "1.0.0",
description = "Order management",
requires = ["auth"],
provides = ["order_svc"], # make("order_svc") resolves OrderService
enabled = True,
routes = "routes",
)
Helpers
from axon import (
# Environment
env, env_bool, env_int, env_list,
# Config
config, config_set,
# Container (bare — no self. needed)
bind, override, extend, make, instance, has_binding,
# Events and jobs
on, emit, filter_event, dispatch, schedule,
# HTTP
abort, url, route,
# Strings
str_slug, str_snake, str_camel, str_pascal, str_uuid, str_random,
str_headline, str_truncate, str_pad, str_between, str_replace,
# Arrays / collections
arr_get, arr_set, arr_only, arr_except, arr_pluck, arr_group_by,
arr_sort, arr_filter, arr_map, arr_first, arr_last, arr_chunk,
arr_sum, arr_avg, arr_min, arr_max, arr_key_by, arr_partition,
arr_merge, arr_deep_merge,
# Values
blank, filled, optional, tap, once, retry,
# Security
bcrypt, bcrypt_check, hash_make, hash_check,
md5, sha256, hmac_sign, hmac_verify,
# Numeric
num_format, num_currency, num_percent, num_ordinal, num_clamp,
# DateTime
now, today, timestamp, now_iso, human_time, diff_in_seconds,
# Files
file_exists, file_get, file_put, file_extension, file_basename,
# Debug
dd, dump,
)
Database configuration
config.yaml supports both a raw connection string and a structured block:
platform:
# Option A — raw connection string (takes priority if set)
database_url: "postgresql://user:pass@localhost/mydb"
# Option B — structured block
database:
engine: postgresql # sqlite | postgresql | mysql | mariadb | mssql
name: mydb
host: localhost
port: 5432
user: myuser
password: secret
echo: false
pool_size: 5
Override any value with env vars:
PLATFORM__DATABASE__ENGINE=postgresql
PLATFORM__DATABASE__HOST=db.prod.internal
PLATFORM__DATABASE__PASSWORD=s3cret
CLI reference
# Run from anywhere
axon create_project <name> Bootstrap a new project
# Run inside a project (./manage <command>)
make:module <name> Scaffold a new module
migrate Run pending migrations
makemigrations [name] Generate a migration
migrate:rollback Roll back the last migration
migrate:fresh --seed Wipe DB and re-run from scratch
runserver [host] [port] Start dev server (default: 0.0.0.0:8000)
createsuperuser Create an admin user
status Show platform status
shell Python REPL with full platform context
dbshell Native DB shell (psql / sqlite3)
Build and publish
pip install build twine
python -m build
twine upload dist/*
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file python_axon-1.0.0.tar.gz.
File metadata
- Download URL: python_axon-1.0.0.tar.gz
- Upload date:
- Size: 110.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.11
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
7ef60ad42f2c06b77dd2be55011c958722cac50ad61db7e0f7e7f82b98aba11c
|
|
| MD5 |
cbc7194ad60636fd1478e4a165337e27
|
|
| BLAKE2b-256 |
055da2caeff9f87e479ef68de4c37b02845eea458df0da9e5c07a5413fefe989
|
File details
Details for the file python_axon-1.0.0-py3-none-any.whl.
File metadata
- Download URL: python_axon-1.0.0-py3-none-any.whl
- Upload date:
- Size: 136.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.11
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b0fb376358dbcbebfe56ba584a216ebccf5990d3b65fb26c584231cf29911a2d
|
|
| MD5 |
57f539902127e847fc61c2eaa2e48184
|
|
| BLAKE2b-256 |
b213990973965d15cab77c0ab905e9f569ff3a93114a7551bfe21b36f3545e06
|