Rustango
A Django-shaped, batteries-included web framework for Rust.
Rustango gives you the productivity of Django or Laravel with the speed and type-safety of Rust: a tri-dialect ORM, auto-migrations, an auto-generated admin, multi-tenancy, first-class auth, and every standard middleware β all shipped, all opt-out via cargo features, and all working on Postgres, MySQL, and SQLite out of the box.
π Docs: rustango.im-fullstack.dev Β· in-repo guides Β· API reference
π³ Cookbook: cookbook_blog/COOKBOOK.md β a runnable, test-backed recipe for every feature below.
Install
[]
# Postgres (default)
= "0.44"
# SQLite β file-backed or in-memory
= { = "0.44", = false, = ["sqlite", "tenancy", "admin", "manage"] }
# MySQL 8+
= { = "0.44", = false, = ["mysql", "tenancy", "admin", "manage"] }
Every capability is a cargo feature you can turn off. Renaming the dep works too β #[derive(Model)] resolves the crate root via proc-macro-crate, so orm = { package = "rustango", version = "0.44" } needs no extra wiring.
An app on SQLite in 30 lines
use Arc;
use ;
use Model as _;
use AppBuilder;
use ;
use Model;
async
async
DATABASE_URL='sqlite:./var/app.db?mode=rwc'
The same code boots on Postgres with DATABASE_URL=postgres://β¦ or MySQL with DATABASE_URL=mysql://β¦ β no changes. Every SQLite connection turns on sensible defaults automatically (PRAGMA foreign_keys = ON, journal_mode = WAL for file-backed DBs, busy_timeout = 5s).
Why Rustango
- One ORM, three backends. Models, queries, migrations, relations, and aggregates emit correct SQL for Postgres, MySQL 8+, and SQLite from the same code.
- Batteries included. Auth (sessions + JWT + OAuth2/OIDC + HMAC + API keys + TOTP), an auto-admin, multi-tenancy, caching, background jobs, email, file storage, signals, i18n, an MCP server, and OpenAPI β not add-ons, in the box.
- Django ergonomics. A project scaffolder (
cargo rustango new),make:*generators,manageCLI,#[derive(Model)]/#[derive(ViewSet)]/#[derive(Serializer)], and admin config blocks that feel familiar coming from Django, DRF, or Laravel. - Opt-out, not opt-in. Everything is a cargo feature. A JSON-only API binary compiles out the admin, templates, and tenancy entirely.
Table of contents
- Quick start
- The ORM
- Migrations
- Auto-admin
- APIs β ViewSets, Serializers, JWT, OpenAPI
- HTML views & forms
- Multi-tenancy
- Authentication & permissions
- Security middleware
- Caching, email, storage, jobs
- Signals, i18n, MCP
- The
manageCLI - Configuration
- Testing
- Comparison
- Documentation
Quick start
For autoreload during development: cargo watch -x run (or bacon run).
Add an app and a model:
use ;
use ;
Full walkthrough: getting started Β· scaffolding.
The ORM
#[derive(Model)] registers a struct in a global inventory and emits typed query, save, and FromRow code. The query builder is Django-shape (.filter(), .exclude(), .order_by(), .annotate(), .select_related(), .prefetch_related()), and the same code runs on all three backends through the Pool enum.
// Filter, order, paginate
let recent = objects
.filter
.exclude
.order_by // true = DESC
.limit
.fetch_pool.await?;
// Aggregate (scalar): .values(&[]) β one row, no GROUP BY
let stats = objects
.values
.annotate
.annotate
.compile?;
Supported: every field type (ints, floats, String, bool, DateTime/Date, Uuid, Json, Decimal, plus PG-only Array/Range/HStore/Vector/Geometry), nullable Option<T>, Auto<T> primary keys, ForeignKey<T> / one-to-one / many-to-many, generic FKs + composite-key FKs (ContentTypes), soft-delete, unique_together / index_together, container-level default scopes, subquery/EXISTS filters, bulk insert/update, transactions, and raw SQL escape hatches. EXPLAIN works on any queryset.
π ORM guide Β· models Β· runnable ORM recipes
Migrations
makemigrations diffs your models against the last migration snapshot and emits JSON operations; migrate applies pending ones and can unapply to roll back. Schema changes (create/alter/drop tables, columns, indexes, constraints, composite FKs) are auto-detected; data migrations are hand-authored with sql + reverse_sql. embed_migrations!("migrations") bakes them into the binary.
π Adopt an existing schema with manage inspectdb β it emits #[derive(Model)] source for every table.
Auto-admin
An admin(...) block on a model gives you a full CRUD admin β list_display, list_filter, search_fields, date_hierarchy, fieldsets, ordering, pagination, and bulk actions β with zero hand-written views:
Also included: a token-driven theme system with dark mode and per-tenant branding (logo/colors via the pluggable Storage trait β S3/R2/B2/MinIO/local), inline child editing (register_admin_inline!), a per-write audit trail with JSON diffs, a users/roles/permissions RBAC surface, a self-serve change-password page, and session invalidation on password rotation.
π Admin guide
APIs β ViewSets, Serializers, JWT, OpenAPI
#[derive(ViewSet)] gives you full REST CRUD β list (page or cursor pagination), retrieve, create (incl. DRF-style bulk create), update, partial update, destroy (soft when the model opts in) β with per-action permission gates:
;
let app = new.merge;
#[derive(Serializer)] is a DRF-shape JSON faΓ§ade (read-only / write-only / renamed / computed method fields, per-field validate, nested FK serialization, and many collections). JWT ships a full lifecycle (issue with custom claims, verify without a DB hit, refresh, re-check permissions, revoke/blacklist). OpenAPI 3.1 auto-derives from your serializers + viewsets, and responses follow JSON:API + RFC 7807 Problem Details. The HTTP QUERY method (RFC 10008) is supported for body-carrying reads.
π ViewSets Β· serializers Β· JWT Β· OpenAPI Β· QUERY method
HTML views & forms
Django-shape class-based views (ListView, DetailView, CreateView, UpdateView, DeleteView) render Tera templates with pagination, filters, bulk actions, FK-display, and business-validation hooks. ModelForm-style forms parse and validate against a model (auto-skipping DB-populated fields), aggregate per-field errors, and emit an insert query. CSRF auto-mounts for form-driven views.
π HTML views
Multi-tenancy
Cli::tenancy().run() boots an operator console, a per-tenant admin, and host-based request dispatch on any backend. Tenants resolve from subdomain, header, path, or port via a resolver chain; each Org picks its isolation strategy:
| Mode | Backends | What it does | When |
|---|---|---|---|
database (default) |
PG, MySQL, SQLite | A dedicated database (or SQLite file) per tenant, one cached pool each. | Enterprise B2B, compliance, sharding β anything on MySQL/SQLite. |
schema |
Postgres only | All tenants share one DB, one per PG schema, one shared pool with SET search_path per request. |
High-N SaaS on PG (500+ small tenants) where connection counts bite. |
Database-mode is the default and works identically everywhere; schema-mode is a Postgres-only pool optimization. Set schema on MySQL/SQLite and the framework returns a clear error pointing you back to database-mode.
π Runnable walkthrough: cookbook Ch. 5 β Multi-tenancy
Authentication & permissions
Pluggable auth backends (model / API-key / JWT β first to recognize the credential wins), argon2id password hashing, typed permission helpers (codename-based, superuser bypass), sessions, TOTP/2FA, API keys, and signed URLs (magic links / time-bounded file downloads).
π passwords Β· sessions Β· backends Β· API keys Β· decorators Β· flows
Security middleware
One hardened middleware chain: request IDs, access logging, rate limiting (in-process or distributed via cache), CORS presets, security-header presets + custom/staged CSP, CSP report endpoint, IP allow/block, CSRF, and per-account lockout. manage check --deploy runs an automated pre-ship audit.
π Security guide Β· middleware catalog
Caching, email, storage, jobs
- Caching β in-memory / Redis backends,
get_or_setmemoization, and per-view response caching (CachePageLayer). caching - Email β a renderer +
Mailable+ job-backed delivery pipeline with pluggable backends. email - Storage & media β pluggable
Storage(S3/R2/B2/MinIO/local),Mediarows, presigned uploads, collections, and tags. files - Background jobs β in-memory or DB queue (
FOR UPDATE SKIP LOCKEDon PG/MySQL 8+, transaction-boundedUPDATE β¦ RETURNINGon SQLite) plus scheduled tasks. jobs
Signals, i18n, MCP
- Signals β model lifecycle (
pre_save/post_save/pre_delete/post_delete) and request lifecycle (request_started/request_finished/got_request_exception). - i18n β
Translatoris Django'sgettextfamily in Rust: per-locale catalogs, base-language fallback,{name}placeholders, CLDR pluralization, plus a DB-override layer and live admin translation editor. i18n - MCP server β the
mcpfeature turns an app into a Model Context Protocol server: AI agents authenticate as tenant-scoped identities and call your framework-exposed tools over JSON-RPC 2.0. mcp
The manage CLI
cargo run -- <cmd> β Django's manage.py in Rust. Migrations (makemigrations / migrate / inspectdb), scaffolders (startapp / make:viewset / make:serializer), system commands (check / check --deploy / shell), and β with the tenancy feature β operator/tenant/superuser provisioning and recovery verbs.
π manage reference
Configuration
Layered config: a <env>_settings.toml pipeline (base β env β local β environment variables), typed sections, compile-time feature reflection, and a deploy audit. Everything has a sensible default; override only what you need.
Testing
A TestClient drives the router as a tower service (no socket), a RequestFactory builds requests, and fixtures seed data. The cookbook's ~150 tests run against live Postgres, MySQL, and SQLite.
π testing
Comparison
| Rustango | Django | Laravel | Rocket | Cot | |
|---|---|---|---|---|---|
| ORM | β | β | β | β | β |
| Auto-migrations | β | β | β | β | β |
| Auto-admin | β | β | β οΈ Filament | β | β |
| Multi-tenancy | β | β οΈ ext | β οΈ ext | β | β |
| JWT lifecycle (refresh + blacklist + custom claims) | β | β οΈ ext | β οΈ Sanctum/Passport | β | β |
| TOTP / 2FA | β | β οΈ ext | β Fortify | β | β |
| Signals | β | β | β Events | β | β |
| Cache backends | β | β | β | β | β οΈ optional |
| Email backends | β | β | β | β | β |
| File storage | β | β οΈ ext | β Flysystem | β | β |
| Scheduled tasks | β | β οΈ Celery beat | β | β | β |
| Security headers | β | β | β οΈ middleware | β Shield | β |
| Test client | β | β | β | β Client | β |
| Project scaffolder | β
cargo rustango new |
β
startproject |
β installer | β | β
cot new |
| File generators | β
make:* |
β οΈ ext | β artisan | β | β |
β shipped Β· β οΈ partial / via extension Β· β not shipped
Documentation
- Guides & tutorials: https://rustango.im-fullstack.dev
- Runnable cookbook:
cookbook_blog/COOKBOOK.mdβ a test-backed recipe for every feature, on all three backends. - In-repo guides (
docs/): getting started Β· models Β· ORM Β· migrations & CLI Β· admin Β· viewsets Β· serializers Β· auth Β· security Β· middleware Β· caching Β· email Β· files Β· jobs Β· i18n Β· MCP Β· testing Β· glossary - API reference: https://docs.rs/rustango
- Changelog:
CHANGELOG.md
Contributing
Git hooks (fmt + secret/debris scan on pre-commit; cargo check --all-features + clippy + lib tests on pre-push) install with bin/install-hooks.sh (sets git config core.hooksPath .githooks). Please run cargo fmt and cargo clippy --all-targets before opening a PR.
License
MIT OR Apache-2.0