Rust-powered async Python web framework — start minimal, grow with rusjango add
Project description
Rusjango
Rust-powered async Python web framework
Start like Flask · Scale like Django · Perform like Rust · Build AI apps natively
What is Rusjango?
Rusjango is a modern Python web framework with a Rust core. It is inspired by Django, FastAPI, Polars, and modern AI-native backend systems.
The core idea is simple:
A developer starts with three files and grows into a full enterprise framework — without ever changing frameworks.
rusjango new myapp # three files: main.py, settings.py, pyproject.toml
rusjango add app users # add a feature
rusjango add orm # add another feature
rusjango add auth # add another feature
rusjango remove app users # safely remove what you no longer need
No bloat by default. Everything is opt-in.
Why Rusjango?
| Problem with existing tools | Rusjango solution |
|---|---|
| Django was built sync-first | Fully async from the ground up |
| New Django project has too many files | Three files: main.py, settings.py, pyproject.toml |
| Django ORM is not async-native | Custom async-first ORM |
| Django admin UI feels outdated | Modern React + Tailwind admin (Phase 5) |
| FastAPI has no built-in ORM or admin | Native ORM + admin built in |
| Python-only frameworks have performance limits | Rust-powered routing, middleware, serialization |
| No framework is AI-native | Native LLM/RAG/agent module (Phase 9) |
| Features pile up and can't be removed | Every feature is removable with rusjango remove |
Features
Available now (Phase 1–3)
- Minimal project scaffold —
rusjango newcreates exactly 3 files - Async HTTP routing —
@app.get,@app.post,@app.put,@app.delete - Path & query parameters — auto type coercion (
int,float,bool,str) - JSON request body — parsed automatically, validated via
Schema - Schema validation — lightweight typed request/response objects
- Middleware system — composable ASGI middleware stack
- Security middleware — host validation +
X-Frame-Options/X-Content-Type-Options - App system —
rusjango add app <name>scaffolds a self-contained app package - INSTALLED_APPS — auto-discovery and route mounting under
/api/<app>/ - Per-app Router isolation — each app owns its own route table, no cross-contamination
- Async ORM — Django-style model API, fully async
- SQLite support — via
aiosqlite, zero config - PostgreSQL support — via
asyncpg - ORM filter lookups —
exact,gte,lte,gt,lt - Migrations —
rusjango migratecreates tables from registered models - Dev server — uvicorn with auto-reload via
rusjango dev - Rust CLI — fast binary with rich help output
Coming soon
| Feature | Phase |
|---|---|
rusjango add docker |
Phase 4 |
rusjango add tests |
Phase 4 |
| Full Schema validation (coercion, defaults, nested) | Phase 4 |
| Admin panel (React + Tailwind, auto CRUD) | Phase 5 |
| Auth system (JWT, sessions, argon2, roles) | Phase 6 |
| Auto API docs (OpenAPI) | Phase 7 |
| Background workers (Redis) | Phase 8 |
| AI/LLM native module (RAG, streaming, tool calls) | Phase 9 |
| Enterprise: audit logs, multi-tenancy, observability | Phase 10 |
Quick Start
Prerequisites
| Tool | Version | Install |
|---|---|---|
| Rust | stable | rustup.rs |
| uv | latest | docs.astral.sh/uv |
| Python | 3.10+ | via uv or system |
1. Clone and build
git clone git@github.com:babar-xagi/Rusjango.git
cd Rusjango
# Install Python dependencies
uv sync
# Build the Rust extension (PyO3 / maturin)
uv run maturin develop -m python/rusjango/pyproject.toml
# Build the CLI binary
cargo build -p rusjango-cli
2. Create your first project
cargo run -p rusjango-cli -- new hello
cd hello
uv sync
cargo run -p rusjango-cli -- dev
Open http://127.0.0.1:8000 — you should see:
{ "message": "Hello Rusjango" }
After
cargo install: Once you runcargo install --path clifrom the repo root, you can userusjangodirectly instead ofcargo run -p rusjango-cli --.
Your First Project — Step by Step
Step 1 — Create project
rusjango new hello
cd hello
Generated structure:
hello/
├── main.py
├── settings.py
└── pyproject.toml
main.py:
from rusjango import Rusjango
app = Rusjango(settings="settings.py")
@app.get("/")
async def home():
return {"message": "Hello Rusjango"}
app.load_installed_apps()
Step 2 — Run the server
rusjango dev
Rusjango running at http://127.0.0.1:8000
Auto-reload enabled
Step 3 — Add an app
rusjango add app school
Creates apps/school/ and registers it in settings.py:
hello/
├── main.py
├── settings.py
├── apps/
│ └── school/
│ ├── __init__.py
│ └── api.py ← routes are at /api/school/...
└── pyproject.toml
apps/school/api.py:
from rusjango import Router
router = Router()
@router.get("/students")
async def list_students():
return [{"name": "Ali"}, {"name": "Sara"}]
Step 4 — Add the ORM
rusjango add orm
rusjango migrate
Adds models.py and schemas.py to every app, creates migrations/, configures SQLite:
# apps/school/models.py
from rusjango.orm import Model, Integer, String
class Student(Model):
id = Integer(primary_key=True)
name = String(max_length=100)
age = Integer(nullable=True)
# apps/school/api.py (upgraded automatically)
from rusjango import Router
from .models import Student
from .schemas import StudentCreate, StudentOut
router = Router()
@router.get("/students")
async def list_students():
students = await Student.all()
return [StudentOut.from_dict(s.to_dict()).dict() for s in students]
@router.post("/students")
async def create_student(data: StudentCreate):
student = await Student.create(name=data.name, age=data.age)
return StudentOut.from_dict(student.to_dict()).dict()
Step 5 — Remove what you don't need
rusjango remove app school
This will remove the 'school' app and unregister it from settings.py.
Do you want to continue? [y/N]
Safe by default. Always asks before deleting.
API Reference
Route decorators
@app.get("/path")
@app.post("/path")
@app.put("/path/{id}")
@app.delete("/path/{id}")
Path parameters
@app.get("/students/{id}")
async def get_student(id: int): # auto-cast to int
return {"id": id}
Query parameters
@app.get("/students")
async def list_students(limit: int = 10, search: str = ""):
...
Request body
from rusjango import Schema
class StudentCreate(Schema):
name: str
age: int
@app.post("/students")
async def create_student(data: StudentCreate):
return data.dict()
HTTP exceptions
from rusjango import HTTPException
@app.get("/admin")
async def admin():
raise HTTPException(403, detail="Forbidden")
Per-app Router
# apps/school/api.py
from rusjango import Router
router = Router() # always create a fresh instance per app
@router.get("/students")
async def list_students():
return []
ORM Reference
Model definition
from rusjango.orm import Model, Integer, String, Text, Boolean
class Post(Model):
id = Integer(primary_key=True)
title = String(max_length=200)
body = Text(nullable=True)
active = Boolean(default=True)
CRUD
# Create
post = await Post.create(title="Hello", body="World")
# Read
post = await Post.get(id=1) # raises DoesNotExist if not found
posts = await Post.all()
posts = await Post.filter(active=True).all()
# Filter lookups: exact (default), gte, lte, gt, lt
posts = await Post.filter(id__gte=5).all()
# Update
await Post.filter(id=1).update(title="Updated")
# Delete
await Post.filter(id=1).delete()
Database settings
# settings.py — SQLite (default)
DATABASE = {
"ENGINE": "sqlite",
"NAME": "db.sqlite3",
"ASYNC": True,
}
# PostgreSQL
DATABASE = {
"ENGINE": "postgresql",
"URL": "postgresql://user:pass@localhost:5432/mydb",
"ASYNC": True,
}
CLI Reference
| Command | Description |
|---|---|
rusjango new <name> |
Create a minimal 3-file project |
rusjango dev |
Start dev server (uvicorn + auto-reload) |
rusjango dev --host 0.0.0.0 --port 9000 |
Custom host/port |
rusjango dev --no-reload |
Disable auto-reload |
rusjango add app <name> |
Scaffold apps/<name>/ and register it |
rusjango remove app <name> |
Remove app (prompts for confirmation) |
rusjango remove app <name> --yes |
Remove without prompting |
rusjango add orm |
Enable async ORM (SQLite by default) |
rusjango remove orm |
Disable ORM, keep model files |
rusjango migrate |
Create database tables from models |
Planned commands:
| Command | Phase |
|---|---|
rusjango add admin / remove admin |
Phase 5 |
rusjango add auth / remove auth |
Phase 6 |
rusjango add docker / remove docker |
Phase 4 |
rusjango add tests / remove tests |
Phase 4 |
rusjango add worker / remove worker |
Phase 8 |
rusjango add ai / remove ai |
Phase 9 |
rusjango add payments / remove payments |
Phase 10 |
Project Structure
Rusjango/
├── Cargo.toml # Rust workspace (core + CLI)
├── pyproject.toml # uv workspace root
├── PROGRESS.md # Phase-by-phase build tracker
│
├── crates/rusjango-core/ # PyO3 Rust extension
│ └── src/
│ ├── lib.rs # Python module entry point
│ └── router.rs # Future: Rust-accelerated routing
│
├── cli/ # rusjango binary (clap)
│ └── src/
│ ├── main.rs # Command definitions
│ ├── new.rs # rusjango new
│ ├── add.rs # rusjango add app
│ ├── remove.rs # rusjango remove app
│ ├── orm.rs # rusjango add/remove orm + migrate
│ ├── dev.rs # rusjango dev
│ ├── project.rs # Template rendering, project root detection
│ └── settings.rs # settings.py manipulation (regex-based)
│
├── python/rusjango/ # Python package (maturin)
│ ├── pyproject.toml
│ └── src/rusjango/
│ ├── __init__.py # Public API: Rusjango, Router, Schema, HTTPException
│ ├── app.py # Rusjango application class + route decorators
│ ├── routing.py # Route compilation, param extraction, handler dispatch
│ ├── asgi.py # ASGI helpers: read_body, send_json, send_error
│ ├── middleware.py # Middleware stack builder
│ ├── security.py # SecurityMiddleware
│ ├── schema.py # Schema base class
│ ├── settings.py # settings.py loader
│ ├── config.py # pyproject.toml discovery
│ ├── apps.py # INSTALLED_APPS loader + router mounting
│ ├── exceptions.py # HTTPException, error envelope
│ ├── server.py # Dev server (uvicorn)
│ └── orm/
│ ├── model.py # Model metaclass + CRUD
│ ├── fields.py # Integer, String, Text, Boolean
│ ├── query.py # QuerySet (lazy, chainable)
│ ├── sql.py # SQL generation (parameterized, injection-safe)
│ └── connection.py # aiosqlite / asyncpg connection management
│
├── templates/ # .tpl files for code generation
│ ├── project/ # rusjango new templates
│ ├── app/ # rusjango add app templates
│ └── orm/ # rusjango add orm templates
│
├── examples/
│ └── hello/ # Working example project (school app + ORM)
│
└── docs/ # Documentation (14 files)
├── 00-overview.md
├── 01-architecture.md
├── 02-getting-started.md
├── 03-cli-reference.md
├── 04-api-design.md
├── 05-orm-guide.md
├── 06-settings-reference.md
├── 07-middleware.md
├── 08-schema-validation.md
├── 09-progress.md
├── 10-contributing.md
└── internals/
├── rust-core.md
├── python-layer.md
└── orm-internals.md
Development Setup
# 1. Clone
git clone git@github.com:babar-xagi/Rusjango.git
cd Rusjango
# 2. Python deps
uv sync
# 3. Build Rust extension (PyO3 / maturin)
uv run maturin develop -m python/rusjango/pyproject.toml
# 4. Build CLI
cargo build -p rusjango-cli
# 5. Run tests
cd python/rusjango
uv run pytest tests/ -v
Testing
tests/test_import.py package version importable
tests/test_asgi.py routing, path params, POST body, HTTPException (5 tests)
tests/test_apps.py INSTALLED_APPS loading, multi-app router isolation (3 tests)
tests/test_config.py pyproject.toml project root discovery
tests/test_orm.py ORM CRUD, filters, update, delete — SQLite (3 tests)
cd python/rusjango
uv run pytest tests/ -v
# 13 passed in ~0.5s
Architecture
┌──────────────────────────────────────────────────────┐
│ Developer Layer (Python) │
│ @app.get("/") | class Student(Model) | Schema │
├──────────────────────────────────────────────────────┤
│ Framework Layer (Python) │
│ routing · ASGI · middleware · ORM query builder │
├──────────────────────────────────────────────────────┤
│ Core Layer (Rust — PyO3) │
│ routing acceleration · serialization · conn pool │
│ (current: version stub + future expansion) │
└──────────────────────────────────────────────────────┘
↑ served by uvicorn (ASGI 3.0)
Python-Rust boundary rule:
Rust handles heavy batch operations — routing, serialization, connection pooling. Python handles business logic — models, handlers, middleware.
Roadmap
| Phase | Goal | Status |
|---|---|---|
| 1 | CLI + minimal API framework | ✅ Complete |
| 2 | Add/Remove app system | ✅ Complete |
| 3 | Async ORM foundation | ✅ Complete |
| 4 | Schema validation + Docker + Tests scaffolding | 🚧 In progress |
| 5 | Admin panel MVP (React + Tailwind) | 📋 Planned |
| 6 | Auth system (JWT, sessions, argon2) | 📋 Planned |
| 7 | API docs + developer experience | 📋 Planned |
| 8 | Worker system (Redis background tasks) | 📋 Planned |
| 9 | AI/LLM native module (RAG, streaming) | 📋 Planned |
| 10 | Enterprise features (multi-tenancy, audit, metrics) | 📋 Planned |
See PROGRESS.md for full details and docs/09-progress.md for per-phase file references.
Documentation
All docs live in docs/:
| File | What it covers |
|---|---|
docs/00-overview.md |
Project vision, problems solved, user types, tech stack |
docs/01-architecture.md |
Monorepo layout, 3-layer arch, request lifecycle |
docs/02-getting-started.md |
Full setup guide from scratch |
docs/03-cli-reference.md |
Every CLI command with options and examples |
docs/04-api-design.md |
Routes, params, body, Schema, Router, middleware |
docs/05-orm-guide.md |
Models, fields, CRUD, filters, migrations |
docs/06-settings-reference.md |
Every settings key explained |
docs/07-middleware.md |
Middleware system, custom middleware |
docs/08-schema-validation.md |
Schema class, validation, limitations |
docs/09-progress.md |
Phase tracker with file references |
docs/10-contributing.md |
How to add features, code style, PR checklist |
docs/internals/rust-core.md |
PyO3, maturin, clap internals |
docs/internals/python-layer.md |
ASGI, routing dispatch, settings isolation |
docs/internals/orm-internals.md |
Metaclass, SQL generation, connection lifecycle |
Contributing
- Read
docs/10-contributing.md - Set up the dev environment (see Development Setup)
- Run the test suite and make sure it passes
- Open a pull request with a clear description
Development rules:
- Keep the default project tiny — never generate unnecessary files
- Every feature must be removable
- Every CLI command must update
settings.pyautomatically - Dangerous commands must ask for confirmation
- ORM must be async-first
- Rust speeds up internals — Python owns business logic
- Documentation is written alongside code, not after
License
MIT — see LICENSE
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distributions
Built Distributions
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 rusjango-0.1.0-cp38-abi3-win_amd64.whl.
File metadata
- Download URL: rusjango-0.1.0-cp38-abi3-win_amd64.whl
- Upload date:
- Size: 120.7 kB
- Tags: CPython 3.8+, Windows x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
06203fe8c74c5ea01e65504f958a403325877cef682ad6cc2ae758540397850f
|
|
| MD5 |
a12d9648b9061b2923d3c2d092f8d560
|
|
| BLAKE2b-256 |
6718d9aa24542c1de555550f928b81b579da7c8488b3e027e3fbd1eea251ddb2
|
File details
Details for the file rusjango-0.1.0-cp38-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.
File metadata
- Download URL: rusjango-0.1.0-cp38-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
- Upload date:
- Size: 251.5 kB
- Tags: CPython 3.8+, manylinux: glibc 2.17+ x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
03b0b06e7bac8b05790f047401c636bda335138116e00572f7be6648cc320062
|
|
| MD5 |
2dbd64b2b0120c7003d318109aa47ed0
|
|
| BLAKE2b-256 |
0ccd09174d19636c3d55e747cd5956d749538c67f8fcb7a2b843809301e73810
|
File details
Details for the file rusjango-0.1.0-cp38-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.
File metadata
- Download URL: rusjango-0.1.0-cp38-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
- Upload date:
- Size: 247.3 kB
- Tags: CPython 3.8+, manylinux: glibc 2.17+ ARM64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
dbadfd78d46d792af54d2b13eb524e2acdebe68cdb6b1b9fbd524e166e49bb5b
|
|
| MD5 |
ee1a5c56ebd647b327829286dd129c68
|
|
| BLAKE2b-256 |
7d7fbcf4446649eb0b22d1c2e049d86963bc55c41b409db13233bbc59f366fde
|
File details
Details for the file rusjango-0.1.0-cp38-abi3-macosx_11_0_arm64.whl.
File metadata
- Download URL: rusjango-0.1.0-cp38-abi3-macosx_11_0_arm64.whl
- Upload date:
- Size: 222.3 kB
- Tags: CPython 3.8+, macOS 11.0+ ARM64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b29b4ef65b3e2225f2d909ff247dd572d8469746d1de74f24c199bdadf6a00c2
|
|
| MD5 |
1f33b4ff6d828bd1967da1a29b5ee238
|
|
| BLAKE2b-256 |
68fbbacdee5a1a9df1d37266b905c2fa62ad961202d10c98320ef283a5e33699
|
File details
Details for the file rusjango-0.1.0-cp38-abi3-macosx_10_12_x86_64.whl.
File metadata
- Download URL: rusjango-0.1.0-cp38-abi3-macosx_10_12_x86_64.whl
- Upload date:
- Size: 223.0 kB
- Tags: CPython 3.8+, macOS 10.12+ x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
7221a132628b6404efe0a942b56e691be0d582574fb62ea8797db9d4f0043bb6
|
|
| MD5 |
6075fce21df4d66bf42dd6a0a6400496
|
|
| BLAKE2b-256 |
ef8547581a9ebca88dc4b958f39e18be828cd876b48545da6a90b91243208a57
|