Skip to main content

Crate rustango

Crate rustango 

Source
Expand description

rustango — a Django-shaped, batteries-included web framework for Rust.

ORM with auto-migrations, auto-admin, multi-tenancy, sessions + JWT + OAuth2/OIDC + HMAC auth, DRF-style serializers + viewsets, signals, caching, media (S3/R2/B2/MinIO), email pipeline, background jobs, scheduled tasks, OpenAPI 3.1 auto-derive, every standard middleware. Postgres + MySQL + SQLite through the same &Pool API, opt-in via Cargo features.

[dependencies]
rustango = "0.41"                                       # Postgres (default)
rustango = { version = "0.41", features = ["sqlite"] }  # SQLite
rustango = { version = "0.41", features = ["mysql"] }   # MySQL 8.0+

§What’s new in v0.41 (May 2026) — Tier 1 ORM gap-closure batch

Django-shape syntax with Rust-shape compile-time safety. Ten ORM tickets across 14 PRs (epic #273):

  • Q!() compile-time macro (#269) — Q!(User.email__icontains = "alice") expands at parse time to the typed-column call. Typo’d field names fail the build.
  • query::Q runtime composable predicate (#263) — for dynamic filter trees (admin chips, REST query params). Operator overloads: & / | / ^ / !.
  • QuerySet::distinct_on (#264) — PG DISTINCT ON native + ROW_NUMBER() portable fallback on MySQL/SQLite. The “latest per group” pattern, tri-dialect.
  • Model::bulk_upsert_pool / Model::bulk_insert_or_ignore_pool (#267) — Django bulk_create(update_conflicts=True) / (ignore_conflicts=True) across PG, MySQL, and SQLite.
  • #[rustango(unique_when(...))] (#265) — partial unique indexes (Django UniqueConstraint(condition=Q(...))). PG/SQLite native; MySQL warns + falls back.
  • DB functions batch 1 (#266) — Cast, LPad, RPad, MD5, SHA1, SHA256, Position, Repeat, Reverse, Sign, Mod, Power, Sqrt — per- dialect emission with clean NotSupported errors on SQLite for the genuinely-missing items (hashes, Reverse, Power/Sqrt without SQLITE_ENABLE_MATH_FUNCTIONS).
  • AggregateBuilder::alias() (#268) — Django 3.2 non- projected annotation. Filter/order by a derived aggregate without paying the column-decode cost.
  • #[rustango(manager(ext = "..."))] (#271) — derive emits the custom-manager extension trait next to the model.
  • sql::explain_pool (#272) — tri-dialect query plan helper. PG EXPLAIN (FORMAT JSON, ANALYZE, BUFFERS), MySQL EXPLAIN ANALYZE / FORMAT=TREE / FORMAT=JSON, SQLite EXPLAIN QUERY PLAN.
  • PG-typed legacy executor deleted (#270, 4 waves) — the bi-API confusion is gone. Fetcher/Counter/Updater/Deleter extension traits + the &PgPool standalone fns + transaction/count_rows/raw_execute/bulk_update are removed. The _on family moved to a #[doc(hidden)] module for macro use only. Migration: drop the trait imports, switch .fetch(pool).fetch_on(pool) (inherent on QuerySet), .delete(pool).delete_on(pool), .execute(pool) (on UpdateBuilder) → .execute_on(pool). Use the _pool family for tri-dialect calls.

Full ticket index: PRs #274–#286.

§What’s new in v0.40 (May 2026)

  • Admin session auth without tenancy (epic #253) — bare admin now ships a styled /login form, signed-cookie sessions (session::SessionSecret), sidebar Logout, password change at /account/password, manage create-admin CLI verb, and is_superuser gating. Opt in via admin::Builder::with_session_auth. Same signing key works across [tenancy::session] + admin::session (different cookie names + payloads so cookies never cross-decode).
  • GenericForeignKey ergonomics + admin inlines (epic #246) — #[rustango(generic_fk(name, ct_column, pk_column))] emits typed target_pool() accessor + set_target_for::<T>() setter. Admin list view collapses the (ct_id, object_pk) pair into one clickable target link. New register_admin_inline_generic! renders polymorphic children as inline panels on the parent’s detail + edit pages. ContentType <select> picker replaces raw integer inputs on the standalone create/edit form.
  • Field help_text#[rustango(help_text = "…")] on any field renders a muted caption below the admin form input. The string lives on core::FieldSchema::help_text so future surfaces (DRF schemas, OpenAPI descriptions) can read the same source.
  • Shared .btn family — admin + operator-console buttons, links, sidebar Logout, inline-panel row links all look like one product. Consistent across bare admin / tenant admin / operator console.
  • Reusable foundationssession::SessionSecret + session::sign (HMAC primitive) and manage_interactive (TTY prompts) promoted to the crate root so the bare admin can reuse them without tenancy compiled in.
  • Runnable demo: examples/gfk_demo exercises every new admin + GFK surface end-to-end on SQLite.

Defaults pull postgres, admin, and runserver (the bi-dialect single-pool server::AppBuilder). Add "tenancy" for the multi-tenant resolver / pools / per-tenant auth. Tenancy is tri-dialect since v0.33: [tenancy::TenantPools] is generic over the backend, database-mode tenants work on every backend, and schema-mode stays Postgres-only by language semantics. Add "mysql" or "sqlite" for additional backends — the same #[derive(Model)] types and _pool ORM API work against any of them. Drop default-features for the bare ORM (no axum, no Tera).

§Quick start

cargo install cargo-rustango
cargo rustango new myblog                 # default: ORM + admin
cargo rustango new myapi --template api   # JSON-only, no admin
cargo rustango new shop --template tenant # multi-tenancy + operator console

Then:

cd myblog
cp .env.example .env                      # set DATABASE_URL
cargo run -- migrate                      # apply bootstrap migrations
cargo run                                 # http://localhost:8080

§Unified manage runner (since v0.16)

Since v0.16 there is one binary that serves HTTP and dispatches manage commands. cargo run starts the server; cargo run -- <verb> runs a CLI command. A scaffolded src/main.rs looks like:

#[rustango::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let _ = dotenvy::dotenv();
    rustango::manage::Cli::new()
        .api(myblog::urls::router())
        .tenancy()                                            // optional, with `tenancy` feature
        .migrations_dir(std::path::Path::new(env!("CARGO_MANIFEST_DIR")).join("migrations"))
        .run()
        .await
}

Common manage verbs (every command supports --help):

GroupVerbs
Migrationsmakemigrations, migrate [target], downgrade [N], showmigrations, add-data-op
Scaffoldersstartapp <name>, make:viewset, make:serializer, make:form, make:job, make:notification, make:middleware, make:test
Systemabout, check, check --deploy, version, docs
Tenancycreate-tenant, create-operator, create-user, list-tenants, create-api-key, grant-perm, revoke-perm, audit-cleanup

§Full reference

See the workspace README for the complete feature matrix, ORM cookbook, viewset / serializer recipes, multi-tenancy guide, and production checklist. The examples/cookbook_blog crate ships a runnable multi-tenant blog with one chapter per feature surface.

Re-exports§

pub use sql::Auto;
pub use rustango_macros as macros;

Modules§

access_log
HTTP access log middleware — one tracing event per request with method / path / status / duration / IP. See access_log::AccessLogLayer. HTTP access log middleware — emit one tracing event per request.
account_lockout
Per-account login lockout — defends against credential stuffing. Cache-backed counter + lock flag. See account_lockout::Lockout. Per-account login lockout — defends against credential stuffing / brute-force attacks that bypass per-IP rate limits.
admin
Auto-generated CRUD admin for rustango models.
api_errors
Standardized API error responses. See api_errors::ApiError. Standardized API error responses.
api_keys
Generic API key generation + verification (argon2id-hashed). See api_keys::generate_key / api_keys::verify_key. Generic API key generation and verification.
api_version
API versioning — extract version from header / query / URL prefix. See api_version::VersionStrategy and api_version::ApiVersion. API versioning extractor — read the requested API version from URL, header, or query parameter.
audit
Audit log — single composite-key table that captures every tracked write (insert, update, delete, soft-delete) across every model whose declaration carries #[rustango(audit(...))].
auth_backends
Pluggable AUTHENTICATION_BACKENDS chain — register an ordered list of auth_backends::AuthBackend impls; the chain returns the first non-None result. Ships RemoteUserBackend for SSO proxy deployments. Issue #54 (partial). Pluggable authentication-backend chain — Django’s AUTHENTICATION_BACKENDS = [...] setting.
auth_decorators
Django-shape access decorators — login_required middleware + ?next= round-trip helpers. Issue #11. Django-shape access decorators — login_required middleware + ?next= round-trip helpers. Issue #11.
auth_flows
Pre-built auth flows — password reset, email verification, magic-link login. See auth_flows::PasswordReset / auth_flows::EmailVerification. Pre-built auth flows — password reset + email verification.
base36
Django-shape base36 integer encoding — used in password reset URLs and other URL-friendly opaque IDs. int_to_base36(n) + base36_to_int(s) round-trip. Django-shape base36 integer encoding — int_to_base36 / base36_to_int.
base62
Django-shape base62 integer encoding — [0-9A-Za-z] 62-char alphabet for short URL IDs (YouTube / bit.ly style). Same shape as base36 but case-sensitive, giving 6.0 bits per char. Django-shape base62 integer encoding — int_to_base62 / base62_to_int.
body_limit
Request body size limit middleware — fast Content-Length rejection returning structured 413 Payload Too Large JSON. Complements axum’s per-extractor DefaultBodyLimit. See body_limit::BodyLimitLayer. Request body size limit middleware.
cache
Pluggable caching layer — cache::Cache trait + cache::NullCache + cache::InMemoryCache. Redis backend behind the cache-redis feature. Pluggable caching layer.
cache_fragment
Fragment caching — Django’s {% cache %} template tag. cache_fragment::cached_render is a handler-side wrapper that consults the cache before invoking a compute closure. Tera lacks the block-tag extension API a 1:1 port would need; the handler-side helper composes naturally with axum and passes the cached HTML through the template context. Issue #16. Fragment caching — Django’s {% cache %} template tag.
casts
Attribute casts (#819) — Cast<C> field wrapper + CastValue trait, with the EncryptedString AEAD-at-rest built-in. Attribute casts — a per-field get/set transform layer (Eloquent $casts / CastsAttributes; Django from_db_value/get_prep_value). Issue #819.
composite_pk
Composite-primary-key patterns — Django 5.2’s CompositePrimaryKey mapped to Auto<i64> surrogate + unique_together. See composite_pk for the canonical worked pattern. Issue #46. Composite-primary-key patterns — Django 5.2’s CompositePrimaryKey adapted to rustango idioms. Issue #46.
compression
Response compression middleware — gzip + deflate via flate2. Honors Accept-Encoding, skips already-compressed bodies and binary content-types. See compression::CompressionLayer. Response compression middleware — gzip + deflate.
config
Layered TOML configuration (slice 8.3).
content_negotiation
HTTP content negotiation — pick the best response format from the client’s Accept header. See content_negotiation::negotiate. HTTP content negotiation — pick the best response format from the client’s Accept header.
contenttypes
ContentType framework (Django-shape) — runtime handle for “any registered model” used by permissions, generic foreign keys, soft-FK prefetch, audit-history admin panels, etc. Sub-slice F.1 of the v0.15.0 plan. Django-shape ContentType framework — sub-slice F.1 of v0.15.0.
cookies
Django-shape Set-Cookie builder — Cookie::new(name, value) .path("/").max_age(secs).http_only().secure().same_site(...) .build() produces an axum-ready HeaderValue. Replaces scattered hand-rolled cookie strings across messages / csrf / jwt / admin / tenancy modules. Django-shape Set-Cookie builder.
core
Core types for rustango.
cors
CORS middleware — cors::CorsLayer for axum routers. CORS middleware — Cross-Origin Resource Sharing for axum routers.
csp_nonce
Per-request CSP nonce middleware — generates a fresh CSPRNG nonce per request, makes it available via Extension<Nonce>, and substitutes 'nonce-__RUSTANGO_NONCE__' in the CSP header so inline <script nonce="..."> tags pass strict CSP. See csp_nonce::CspNonceLayer. Per-request CSP nonce middleware.
csv
Minimal RFC 4180 CSV writer — zero deps. See csv::CsvWriter. Minimal CSV writer — RFC 4180 compliant, zero deps.
csv_response
axum response wrapper for CSV exports — sets Content-Type + optional Content-Disposition so browsers prompt a “Save as…” download. See csv_response::CsvResponse. axum response wrapper for CSV exports — sets the right Content-Type + an optional Content-Disposition so browsers prompt a “Save as…” download.
databases
Named multi-database registry + QuerySet::using(alias) (#332/#400). Named multi-database registry — Django’s DATABASES setting + QuerySet.using(alias) (issues #332 / #400).
dateformat
Django-shape date format-character expander — converts a Django template {{ obj|date:"Y-m-d H:i" }} format string into the matching strftime output. Mirrors django.utils.dateformat. Django-shape date format-character expander.
dateparse
Django-shape ISO 8601 date / time / datetime / duration string parsers — dateparse::{parse_date, parse_time, parse_datetime, parse_duration}. Mirrors django.utils.dateparse.*. Django-shape ISO 8601 / W3C datetime parsers.
dates
Django django.utils.dates parity — month / weekday name lookups: month_full(m), month_abbr(m), month_ap(m), weekday_full(d), weekday_abbr(d). English-only by design (i18n is a separate concern). Django django.utils.dates parity — month / weekday name maps.
dbshell
manage dbshell — spawn psql / mysql / sqlite3 for the current DATABASE_URL. Issue #56 (partial). manage dbshell — spawn the native CLI client (psql, mysql, sqlite3) for the current DATABASE_URL. Django’s dbshell. Issue #56 (partial).
default_filters
Django defaultfilters template filters — pluralize, truncatewords, linebreaks, default_if_none. See default_filters. Issue #61. Django defaultfilters template filters as Tera filters. Issue #61.
distributed_lock
Distributed locks backed by cache::Cache — “only one worker at a time runs this task” with TTL-based crash recovery and token-checked release. See distributed_lock::DistributedLock. Distributed locks backed by Cache.
email
Email backends — email::Mailer trait + console/in-memory/null backends. Email backend layer — pluggable async email sending.
email_jobs
Send email off the request path via the crate::jobs queue. Pairs the email::Mailer trait with the queue’s retry-with- backoff so transient SMTP failures don’t blow up handlers. See email_jobs::register_email_job + email_jobs::dispatch_email. Send email off the request path via the crate::jobs queue.
email_templates
Tera-rendered email helpers — bridge crate::email mailers and the Tera templating engine. Each email = <name>.subject.txt + <name>.txt + optional <name>.html. See email_templates::EmailRenderer. Tera-rendered email helpers — bridge the existing crate::email mailer trait and the Tera templating engine (already a dep on the admin feature).
env
Typed environment variable readers — required / with_default / optional / list / duration_secs / duration_millis. Typed environment variable readers — pydantic-settings / django-environ shape.
etag
ETag middleware — hashes 2xx response bodies, returns 304 when If-None-Match matches. See etag::EtagLayer. ETag middleware — hashes response bodies and serves 304 Not Modified when the client’s If-None-Match matches.
events
Domain event bus — typed pub-sub for application-level events decoupled from the ORM. Use this for cross-component fanout (OrderPlaced → mail + billing + audit handlers); use signals for per-Model lifecycle hooks. See events::EventBus. Domain event bus — typed pub-sub for application-level events decoupled from the ORM. Closes future-backlog item #45 (“internal event bus / domain event dispatch decoupled from ORM signals”).
feature_flags
Feature flags / killswitches backed by cache::Cache — boolean killswitch + per-user override + stable percentage rollout. See feature_flags::FeatureFlags. Feature flags / killswitches backed by the Cache trait.
fixtures
Test fixture loader — seed a database from JSON files. See fixtures::Fixture. Test fixture loader — seed a test database from JSON files.
flatpages
Static “flat pages” — django.contrib.flatpages. Build a flatpages::FlatPageMap (path → flatpages::FlatPage) and mount flatpages::flatpages_middleware on your axum router; matching requests serve the page body with text/html (or a custom content-type). Bring your own Tera wrapping. Issue #57. Static “flat pages” — django.contrib.flatpages.
forms
Form parsing, validation, and saving — shared between the auto-admin and user route handlers.
health
Health check endpoints — /health (liveness) + /ready (readiness). See health::health_router. Health check endpoints — /health (liveness) and /ready (readiness).
hmac_auth
AWS-style canonical request signed with SHA-256, replay-bounded by an X-Date tolerance window. See hmac_auth::HmacAuthLayer. HMAC-signed request authentication for service-to-service traffic.
host_validation
Host-header allowlist middleware — Django ALLOWED_HOSTS parity. See host_validation::AllowedHostsLayer. Host-header allowlist middleware — Django parity for the ALLOWED_HOSTS setting + the host-validation step SecurityMiddleware runs implicitly before every view.
http_client
Opinionated HTTP client — reqwest wrapper with sane timeouts, retry on idempotent verbs / transient failures, default User-Agent. See http_client::HttpClient. Opinionated HTTP client — reqwest wrapper with sane timeouts, exponential-backoff retries on idempotent verbs / transient failures, and a default User-Agent.
http_date
Django-shape HTTP date parser + formatter — RFC 1123 / RFC 850 / ANSI C asctime parsing per RFC 7231 §7.1.1.1; IMF-fixdate output per RFC 1123. http_date::http_date(secs) + parse_http_date(s). Django-shape HTTP date parser + formatter.
http_methods
Django-shape @require_http_methods(['GET', 'POST']) / @require_GET / @require_POST / @require_safe decorators as tower middleware. Rejects unallowed methods with 405 Method Not Allowed + RFC 7231-compliant Allow: header listing the accepted set. Django-shape HTTP method restriction layer — mirrors django.views.decorators.http.{require_http_methods, require_GET, require_POST, require_safe}.
humanize
Django humanize template filters — intcomma, intword, naturalsize, ordinal, apnumber, naturaltime, naturalday. See humanize. Issue #17. Django humanize template filters as Tera filters. Issue #17.
i18n
Internationalization (i18n) — translation lookups + Accept-Language negotiation. See i18n::Translator and i18n::negotiate_language. Internationalization (i18n) — translation lookups + Accept-Language negotiation.
idempotency
Idempotency-key middleware (Stripe-shape) — replays a stored successful response when a write request arrives with the same Idempotency-Key. Backed by any cache::Cache. See idempotency::IdempotencyLayer. Idempotency-key middleware (Stripe-shape).
inheritance
Model-inheritance patterns — Django’s Meta.abstract, multi-table, and proxy shapes adapted to Rust idioms. See inheritance for the canonical worked mappings. Issue #51. Model-inheritance patterns — Django’s Meta.abstract, multi-table, and proxy shapes adapted to Rust. Issue #51.
ip_filter
IP allowlist / blocklist middleware. See ip_filter::IpFilterLayer. IP allowlist / blocklist middleware — gate routes by client IP.
jobs
Background job queue with worker pool — async work outside the request lifecycle. Currently in-memory only. See jobs::JobQueue. Background job queue — async work outside the request lifecycle.
jsonapi
JSON:API v1.1 response envelope adapter — wrap a flat serde_json::Value (typical serializer output) into the {"data": {"type", "id", "attributes": {...}}} shape that JSON:API clients expect. See jsonapi::to_resource + jsonapi::to_collection. JSON:API v1.1 response shape adapter.
jti_store
Pluggable JTI revocation / single-use store. v0.47 extracts the in-memory Mutex<HashMap> that was hard-coded into [tenancy::jwt_lifecycle::JwtLifecycle] and the impersonation handoff into a jti_store::JtiStore trait so multi-instance deployments can plug in Redis / DB-backed stores. Pluggable JTI (JWT ID) revocation / single-use store.
jwt
Standalone HS256 JWT — sign / verify / decode for magic links, microservice tokens, third-party SSO. See jwt::encode + jwt::decode. Minimal JWT (HS256) — sign, verify, decode.
list_params
Shared list-endpoint query-parameter helpers — single source of truth for the reserved-key skip list, ?ordering= parsing, and ?page_size= clamping. Used by both viewset::handle_list and the template_views::ListView CBV. Closes the drift hazard flagged in issue #809. Shared helpers for list-endpoint query-parameter parsing.
logging
One-call tracing-subscriber setup. See logging::setup / logging::Setup. Tracing-subscriber setup helpers — the boilerplate every rustango app writes by hand becomes one call.
lorem
Django-shape lorem ipsum generators — placeholder text for demos, test fixtures, template scaffolds. lorem::words(n), lorem::paragraphs(n), lorem::sentence(). Django-shape lorem ipsum placeholder text — mirrors django.utils.lorem_ipsum.
mailable
Laravel-shape Mailable trait — declare an email type as a struct that owns its template + recipient logic. Pairs with email_templates::EmailRenderer (rendering) and email_jobs (off-request delivery). See mailable::Mailable. Laravel-shape Mailable trait — declare an email type as a struct that owns its own template + recipient logic. Pairs with crate::email_templates::EmailRenderer (template rendering) and crate::email_jobs (off-request delivery).
maintenance
Maintenance-mode middleware — return 503 with Retry-After from a shared atomic flag, so an orchestrator can drain traffic before a deploy / migration without killing in-flight requests. See maintenance::MaintenanceFlag + maintenance::MaintenanceLayer. Maintenance-mode middleware — return 503 with Retry-After from a shared flag, so an orchestrator (or a sidecar) can drain traffic before a deploy / migration without killing in-flight requests.
manage
Unified manage runner — collapses src/main.rs + src/bin/manage.rs boilerplate into one manage::Cli builder. Tenancy variant available when the tenancy feature is on. Behind the manage feature (default-on) which pulls a minimal axum + tokio surface so bare-API projects (no admin) can still use the dispatcher. Unified manage runner — collapses src/main.rs + src/bin/manage.rs boilerplate into one builder so apps stop hand-writing the dispatcher.
manage_interactive
TTY-gated interactive prompts for manage verbs — ask(prompt) reads a line, ask_password(prompt) reads a password without echoing. Both return Ok(None) on non-TTY stdin so scripted callers keep the existing “missing required flag” error path.
manager
Custom Manager / QuerySet-extension pattern — Django’s class PublishedManager(Manager) / QuerySet.as_manager() adapted to Rust’s extension-trait idiom. See manager for the canonical worked examples. Issue #52. Custom Manager / QuerySet-extension pattern — Django’s class PublishedManager(Manager) and QuerySet.as_manager() adapted to Rust. Issue #52.
media
First-class Media model — Postgres-backed file references with direct-browser upload, CDN-aware URLs, soft delete + orphan purge. See media::Media + media::MediaManager. First-class Media model — a real #[derive(Model)] row that references a file in the crate::storage::Storage layer.
messages
Django messages framework — messages.success/info/warning/error/debug flash storage backed by a signed cookie. Issue #9. Django’s messages framework, ported to a cookie-backed signed-storage shape. Issue #9.
method_override
HTTP method override — rewrite POST → PUT/PATCH/DELETE based on X-HTTP-Method-Override header or _method form field, so HTML forms can drive REST routes. See method_override::MethodOverrideLayer. HTTP method override — rewrite POST → PUT / PATCH / DELETE based on a hidden form field or header.
metrics
Prometheus-format metrics — counters + histograms exposed at /metrics. Pure-Rust, no Prometheus client crate. See metrics::MetricsRegistry + metrics::metrics_router. Prometheus-format metrics — counters + histograms exposed at /metrics.
migrate
Migrations for rustango.
notifications
Multi-channel notifications — fan one notification out to mail / database / log / broadcast channels. See notifications::notify. Multi-channel notifications — fan one notification out to mail / database / log / broadcast channels.
numberformat
Django-shape number formatter — numberformat::format(value, decimal_sep, decimal_pos, grouping, thousand_sep). Mirrors django.utils.numberformat.format. Tri-byte grouping (thousands), per-locale decimal/thousand separator override, optional fixed decimal-place width. Django-shape number formatter — mirrors django.utils.numberformat.format.
oauth2
OAuth2 / OIDC swiss-knife — social login that works for both pure OAuth2 (GitHub, Discord) and OIDC (Google, Microsoft, Keycloak) providers via the /userinfo endpoint. Per-tenant via oauth2::OAuth2Registry. Optional axum router under oauth2::router (requires the admin feature). OAuth2 / OIDC swiss-knife — one type, every provider.
openapi
OpenAPI 3.1 spec builder + Swagger UI / Redoc viewer routes. Hand-build a spec with openapi::OpenApiSpec and mount it under openapi::router::openapi_router (requires the admin feature). OpenAPI 3.1 spec builder + optional Swagger UI router.
pagination
Pagination helpers — RFC 5988 Link headers + cursor params. See pagination::LinkHeaderBuilder. Pagination helpers — three shapes for different surfaces.
password_hashers
Pluggable PASSWORD_HASHERS chain with upgrade-on-login — register an ordered list of password_hashers::PasswordHashers; the first is preferred for new hashes, every entry verifies its own format, and successful logins against an older hasher return a freshly-rehashed value so the caller can transparently upgrade the stored hash. Issue #54 (partial). Pluggable password-hasher chain with upgrade-on-login — Django’s PASSWORD_HASHERS = [...] setting.
password_validators
Pluggable AUTH_PASSWORD_VALIDATORS chain — run an ordered list of password_validators::PasswordValidators at signup / password-change. Built-ins: MinimumLengthValidator, MaximumLengthValidator, NumericPasswordValidator, UserAttributeSimilarityValidator, CommonPasswordValidator. Issue #54 (partial). Pluggable password validator chain — Django’s AUTH_PASSWORD_VALIDATORS = [...] setting.
passwords
Generic password hash/verify + strength heuristic. See passwords::hash. Generic password hashing + strength checking.
problem_details
RFC 7807 “Problem Details for HTTP APIs” — standardized error responses with application/problem+json. Sister to api_errors. See problem_details::ProblemDetails. RFC 7807 “Problem Details for HTTP APIs” — standardized error responses with the canonical application/problem+json content type.
prunable
Model pruning — declarative bulk-removal of stale rows. Eloquent Prunable parity. See prunable::Prunable + register_prunable!. Model pruning — Eloquent Prunable / Django “scheduled bulk removal” parity. Issue #822.
query
Query layer for rustango.
random
Django-shape random-string helpers — get_random_string, get_random_token_urlsafe. CSPRNG-backed, suitable for session IDs, reset tokens, verification codes. Django-shape random-string helpers — get_random_string / get_random_token_urlsafe.
rate_limit
Token-bucket rate limiting middleware — rate_limit::RateLimitLayer. Per-IP, per-header, or global. Returns 429 with Retry-After when exhausted. Token-bucket rate limiting middleware for axum routers.
rate_limit_cache
Cache-backed rate limiting middleware — fixed-window counter via the cache::Cache trait. Pair with RedisCache for distributed enforcement across multiple processes / replicas. See rate_limit_cache::CacheRateLimitLayer. Distributed rate limiting via the Cache trait.
real_ip
Real-IP extraction for apps behind a trusted reverse proxy (Cloudflare / nginx / ELB / etc). Parses X-Forwarded-For, X-Real-IP, CF-Connecting-IP, or RFC 7239 Forwarded and stuffs the resolved client IP into request extensions. See real_ip::RealIpLayer. Real-IP extraction middleware for apps behind a trusted reverse proxy.
redirects
Table-driven HTTP redirects — django.contrib.redirects. Build a redirects::RedirectMap (programmatically or from a CSV) and mount redirects::redirects_middleware on your axum router; matching requests short-circuit with a 301/302 response and the canonical URL in Location, query strings preserved. Issue #57. Table-driven HTTP redirects — django.contrib.redirects.
request_id
Request ID middleware — assign per-request correlation IDs, honor inbound X-Request-Id for end-to-end propagation. See request_id::RequestIdLayer. Request ID middleware — assign a unique ID to every incoming request.
request_timeout
Per-request handler timeout — kills handlers that exceed the configured duration and returns 504 Gateway Timeout. Caps the blast radius of wedged DB queries / external HTTP calls. Wired from Settings.server.request_timeout_secs automatically by Cli::with_settings_from_env(). See request_timeout::RequestTimeoutLayer. Per-request timeout middleware. Wraps an axum router so any handler that takes longer than the configured duration gets killed and the client receives 504 Gateway Timeout instead of a hung connection.
scheduler
In-process scheduled task runner — fire async jobs at fixed intervals. See scheduler::Scheduler. In-process scheduled task runner — fire async jobs at fixed intervals.
secrets
Pluggable secrets backend — secrets::Secrets trait + secrets::EnvSecrets
security_headers
Security headers middleware — HSTS / X-Frame-Options / nosniff / Referrer-Policy / Permissions-Policy / CSP. See security_headers::SecurityHeadersLayer. Security headers middleware — HSTS, X-Frame-Options, X-Content-Type-Options, Referrer-Policy, Cross-Origin-Opener-Policy, and a Content-Security-Policy builder.
serializer
DRF-style serializer layer — #[derive(Serializer)] + serializer::ModelSerializer. Typed JSON output from model instances with field control and validation. DRF-style serializer layer — typed JSON output from model instances.
server
Django-style runserver — [server::Builder] owns every line of boilerplate every tenancy app would otherwise rewrite (DB pool, resolver chain, host dispatch, operator console, bind + serve).
server_timing
Server-Timing header middleware — surface per-request stage durations to the browser DevTools “Network” panel. See server_timing::ServerTimingLayer + server_timing::Timings. Server-Timing header middleware — surface per-request stage durations to the browser DevTools “Network → Timing” panel.
session
Signed-cookie session primitives — HMAC-SHA256 key wrapper + sign(secret, msg) helper. Shared by every layer that ships a signed cookie ([tenancy::session], admin::session) so the crypto lives in one place. See session::SessionSecret.
sessions
Server-side sessions backed by cache::Cache — opaque cookie ID, server-stored bag of typed values, revocable per-session. See sessions::Session + sessions::SessionStore. Server-side session store backed by crate::cache::Cache.
shortcuts
Django-shape view shortcuts — get_object_or_404 / get_list_or_404 / render / redirect. See shortcuts. Issue #10. Django-shape view shortcuts. Issue #10.
signals
Django-shape model signals — signals::connect_post_save etc. Receivers register globally per model type and run sequentially. Django-shape model signals — pre_save, post_save, pre_delete, post_delete.
signed_url
Signed URL helpers — HMAC-SHA256 with optional expiry. See signed_url::sign / signed_url::verify. Signed URL helpers — tamper-evident URLs with optional expiry.
signing
Django-shape generic value signer — signing::Signer::sign(value)
sitemaps
XML sitemap rendering — django.contrib.sitemaps. Build a Sitemap impl (or pass a Vec<SitemapEntry> directly) and call sitemaps::render_sitemap; for large sites use sitemaps::render_sitemap_index to point crawlers at multiple child sitemaps. Issue #57. XML sitemap rendering — Django’s django.contrib.sitemaps.
soft_delete
Soft-delete query helpers — active_filter / trashed_filter / compose_with_active / soft_delete / restore / purge for any model carrying #[rustango(soft_delete)]. See soft_delete.
sql
SQL compilation and execution for rustango.
sse
Broadcast event bus — fan-out for SSE / WebSocket / signal-driven push. See sse::EventBus. Broadcast event bus — fan one message out to every connected subscriber. The foundation for Server-Sent Events (SSE) and other real-time push patterns.
ssl_redirect
HTTP → HTTPS redirect middleware — Django SECURE_SSL_REDIRECT
static_files
Static file serving — read files from a directory with sensible Content-Type, Cache-Control, Last-Modified, and 304 support. See static_files::StaticFiles + static_files::static_router. Static file serving — read files from a directory and ship them with sensible Content-Type, Cache-Control, and Last-Modified headers, plus If-Modified-Since 304 support.
storage
File storage backends — storage::Storage trait + LocalStorage + InMemoryStorage. File storage backends — upload, retrieve, delete files via a pluggable trait.
syndication
RSS 2.0 + Atom 1.0 feed rendering — django.contrib.syndication. Build a syndication::Feed with channel metadata + syndication::FeedItems and call syndication::render_rss or syndication::render_atom. Issue #57. RSS 2.0 + Atom 1.0 feed rendering — django.contrib.syndication.
template_context_processors
Django-shape template context processors — see template_context_processors. Issue #384. Django-shape template context processors — issue #384.
template_debug
Django-shape DEBUG template-error overlay — see template_debug. Issue #386. Django-shape DEBUG template-error overlay — issue #386.
template_extensions
Django-shape custom template filters + functions — see template_extensions. Issue #383. Django-shape custom template tags + filters — issue #383.
template_views
Generic class-based views for HTML templates (Django-shape) — ListView, DetailView, CreateView, UpdateView, DeleteView over #[derive(Model)] schemas, rendered through Tera. Sibling of viewset for the JSON/API side. See template_views for usage and the canonical Tera context shape.
test_assertions
Django-shape test assertion helpers — assert_contains / assert_redirects / assert_status / assert_messages on axum Response objects. Issue #40. Django-shape assertion helpers for axum response objects. Issue #40.
test_client
Test client — fire HTTP requests against an axum::Router in tests without binding a real socket. See test_client::TestClient. Test client — fire HTTP requests against an axum::Router in tests without binding a real socket.
test_data
Class-level test fixtures — Django’s setUpTestData(cls). Wraps std::sync::OnceLock / tokio::sync::OnceCell with the setup_test_data! / setup_test_data_async! macros so test fixtures lazily init once per test-binary process. Issue #42. Class-level test fixtures — Django’s setUpTestData(cls).
test_db
Test-time DB isolation — Django’s TestCase transaction wrapping. test_db::with_rollback runs an async closure inside a transaction that always rolls back, so test mutations don’t leak into the next test. Issue #39 partial. Test-time DB isolation — Django’s TestCase / TransactionTestCase analogs. Issue #39.
test_factory
Django-shape test factories — factory_boy parity. test_factory::Sequence counter + test_factory::Factory trait with build_batch for declarative model builders. Issue #432. Django-shape test factories — factory_boy parity.
test_filter
Tag-based test filtering — Django’s @tag('slow') + manage test --tag fast --exclude-tag slow. Drop tags!("slow") at the top of a #[test] body; the test self-skips when the RUSTANGO_TEST_TAGS / RUSTANGO_TEST_EXCLUDE_TAGS env vars filter it out. Issue #45. Tag-based test filtering — Django’s @tag('slow', 'core') + manage test --tag fast --exclude-tag slow. Issue #45.
test_server
Live HTTP server for tests — Django’s LiveServerTestCase. Binds axum::Router to a random localhost TCP port and runs it on a background task. Use when in-process test_client::TestClient routing isn’t enough (Selenium, websockets, code reading scheme/host headers). Issue #39 partial. Live HTTP server for tests — Django’s LiveServerTestCase.
test_settings
Test-only Settings overlay — Django’s @override_settings / with self.settings(...). Wraps a tokio::task_local! config::Settings overlay so test code can install per-task configuration without touching process-global state. test_settings::current reads through the overlay → fallback chain. Issue #43. Test-only Settings overlay — Django’s @override_settings / with self.settings(...). Issue #43.
text
Text utilities — slugify, html_escape, truncate. Text utilities — slug generation, HTML escaping, truncation.
timesince
django.utils.timesince parity — timesince / timeuntil plain-function API with Django-style depth control (“4 days, 6 hours”). Public Rust surface; Tera filter wrappers live in humanize. Django django.utils.timesince parity — human duration strings.
totp
TOTP — RFC 6238 time-based one-time passwords for 2FA. See totp::generate / totp::verify / totp::otpauth_url. TOTP — Time-based One-Time Passwords (RFC 6238) for 2FA.
tracing_layer
Per-request tracing span with W3C / OpenTelemetry-conventional field names + traceparent header propagation. Hook tracing_opentelemetry::layer() in your subscriber for free distributed tracing. See tracing_layer::TracingLayer. Per-request tracing span with W3C / OpenTelemetry-conventional field names + traceparent header propagation.
trailing_slash
Trailing-slash redirect middleware — canonicalize URL paths (Django APPEND_SLASH / Rails trailing_slash shape). See trailing_slash::TrailingSlashLayer. Trailing-slash redirect middleware — canonicalize URL paths.
uploads
Multipart file upload helper — wraps axum’s multipart extractor + the storage::Storage trait. See uploads::save_uploads + uploads::UploadConfig. Multipart file upload helper — wraps axum’s multipart extractor + the crate::storage::Storage trait so a file upload handler is a one-liner instead of buffering / size-checking / extension- validating glue.
url_codec
Django django.utils.encoding + django.utils.http URL/IRI/URI helpers — url_encode, uri_to_iri, iri_to_uri, escape_uri_path, filepath_to_uri, urlsafe_base64_encode / _decode, etc. Originally an internal pub(crate) module used by signed_url, auth_flows, and [tenancy::admin]; promoted to pub so consumer crates can reach the Django-parity helpers directly (otherwise the uri_to_iri / filepath_to_uri / escape_uri_path / is_uri_reserved helpers shipped by the django.utils parity sweep would be unreachable). URL codec helpers — application/x-www-form-urlencoded percent decoder + RFC-3986 percent encoder + Django-shape urlsafe base64.
urls
Named URL reversal — Django’s reverse(name, params) + get_absolute_url(). Pair with register_url!. Issue #8. Named URL reversal — Django’s reverse() + get_absolute_url(). Issue #8.
validators
Django-shape standalone validators — validate_email, validate_url, validate_slug, validate_min_length / validate_max_length, validate_min_value / validate_max_value. See validators. Issue #54. Django-shape standalone validators. Issue #54.
viewset
DRF-style ModelViewSet — five REST endpoints for any Model table in ~5 lines. See viewset::ViewSet.
webhook
Webhook signature verification (HMAC-SHA256). See webhook::verify_signature. Webhook signature verification — HMAC-based, constant-time.
webhook_delivery
Outbound webhook delivery — POSTs HMAC-signed JSON via the background job queue (so retries with exponential backoff are free). See webhook_delivery::WebhookSubscription. Outbound webhook delivery — POSTs an HMAC-signed JSON payload to a subscriber URL via the background job queue.
welcome
First-run welcome page — confidence signal that rustango is wired up. Mount under / while bootstrapping; replace once you have content. See welcome::welcome_router. First-run welcome page — confidence signal that rustango is wired up.
ws
WebSocket handler scaffold — fan-out via sse::EventBus with auto JSON encode/decode + keep-alive ping. See ws::WsHub + ws::ws_handler. WebSocket handler scaffold — fan-out via the SSE [EventBus].

Macros§

Q
Q!() — Django-shape filter syntax compile-time-resolved against typed columns. Each invocation expands to the equivalent typed-column method call, so field-name typos fail the build. See rustango_macros::Q for the supported lookup suffixes.
atomic
Sugar over atomic that wraps the body in Box::pin(async move { … }) so callers don’t have to. Identical semantics:
embed_migrations
Bake every migration file in a directory into the binary at compile time, for shipping a single-binary distribution. Pair with migrate::migrate_embedded. Bake every *.json migration file in a directory into the binary at compile time. Returns a &'static [(&'static str, &'static str)] of (name, json_content) pairs, lex-sorted by file stem.
register_admin_computed
Register an admin computed field. Pair with a #[derive(Model)] type whose admin(list_display = "…") names this field.
register_admin_inline
Register an admin inline. The parent / child arguments must match the ModelSchema::table of two #[derive(Model)] types already in the registry.
register_admin_inline_generic
Register a generic admin inline. Same shape as [register_admin_inline!] but takes ct + pk instead of fk.
register_admin_list_filter
Register a custom list filter. Pair with the table whose admin list view should expose the filter card.
register_admin_object_permission
Register a Django-shape has_<action>_permission predicate scoped to one model.
register_admin_queryset
Register an admin queryset hook scoped to one model.
register_admin_view
Register a custom admin view scoped to one model.
register_migration_callback
Register a named migration callback. Pair the chosen name with a {"callback": {"name": "..."}} entry in your migration JSON’s forward array.
register_prunable
Register a Prunable impl with the inventory walker. The manage prune CLI verb walks every entry on each run; the in-process prune_all / prune_pretend helpers do the same.
register_template_context_processor
Register a template context processor. Pair with apply_to_context at the handler site (or rely on the framework’s CBV wrappers, which call it automatically).
register_template_filter
Register a custom Tera filter globally. Picked up by apply_to_tera at template-engine construction time.
register_template_function
Register a custom Tera function globally. Picked up by apply_to_tera at template-engine construction time.
register_url
Register a named URL pattern at module-load time. Picks up rustango::inventory so callers don’t need their own dep.
setup_test_data
Class-level synchronous test fixture — Django’s setUpTestData for fixtures that don’t need an async runtime. Wraps a std::sync::OnceLock in a function-call surface.
setup_test_data_async
Class-level async test fixture — Django’s setUpTestData for fixtures that need to hit the database (the common case for model-row fixtures). Wraps a tokio::sync::OnceCell so concurrent first-access calls all wait on the same future, with only one actually running the init body.
tags
Declare this test’s tags and early-return if the current RUSTANGO_TEST_TAGS / RUSTANGO_TEST_EXCLUDE_TAGS env vars say it shouldn’t run. Place at the top of the test body — before any setup that you don’t want to run for filtered-out tests.
with_rollback
Sugar around with_rollback that wraps the body in Box::pin(async move { … }) so callers don’t have to. Identical semantics:
with_truncate_after
Sugar around with_truncate_after mirroring the with_rollback! macro shape:

Enums§

RustangoError
Unified error type for app-level code. From impls cover every module in the framework so ? Just Works in handlers.

Type Aliases§

RustangoResult
Standard alias.

Attribute Macros§

main
#[rustango::main] — the Django-shape runserver entrypoint. Wraps #[tokio::main] with a default tracing-subscriber boot (env-filter, falling back to info,sqlx=warn). Available behind the runtime feature, which tenancy implies. #[rustango::main] — the Django-shape runserver entrypoint. Wraps #[tokio::main] and a default tracing_subscriber initialisation (env-filter, falling back to info,sqlx=warn) so user main functions are zero-boilerplate:

Derive Macros§

Form
#[derive(Form)] — implements forms::Form so a struct can be parsed from an HTTP form payload with multi-error validation. Re-exported only when the forms feature is on. Derive rustango::forms::Form (slice 8.4B). Generates a parse(&HashMap<String, String>) -> Result<Self, FormErrors> impl that walks every named field and:
Model
#[derive(Model)] — populates the inventory registry the admin walks, generates objects() / typed columns / insert / delete / save. Derive a Model impl. See crate docs for the supported attributes.
Serializer
#[derive(Serializer)] — implements serializer::ModelSerializer on a struct, generating from_model, a custom serde::Serialize (respecting write_only), and writable_fields. Re-exported when the serializer feature is on. Derive rustango::serializer::ModelSerializer for a struct. (intra-doc link disabled — the macro crate doesn’t depend on rustango itself, so rustdoc can’t resolve the path.)
ViewSet
#[derive(ViewSet)] — generates a router(prefix, pool) -> axum::Router associated method on a marker struct, wiring the full CRUD ViewSet in one annotation. Re-exported under admin or tenancy (the generated router(...) expands to __axum::Router, which admin provides); the generated router(...) works without tenancy, and tenant_router(...) adds the multi-tenant path when tenancy is also enabled. Derive a router(prefix, pool) -> axum::Router associated method on a marker struct, wiring the full CRUD ViewSet in one annotation.