Runique — l'expérience développeur Django, en Rust type-safe
Déclarez un modèle une fois, et vous récupérez la table en base, la migration, un formulaire type-safe et un panel admin complet — sans câblage supplémentaire. Runique apporte la productivité de Django à Rust sans vous demander de renoncer à sa sécurité ni à ses performances. Construit sur Axum, SeaORM et Tera, il s'efface une fois le code répétitif écarté.
Statut, sans détour : développement actif. Le crate du framework (
runique) fait foi ;demo-appest une vraie application testée contre lui, pas une démo jetable. Le panel admin est en bêta. Rien ci-dessous n'est enjolivé — voir l'état du projet pour la version sans filtre.
🌍 Langues : English | Français
Des macros déclaratives, pas du code répétitif
model! {
Article,
table: "articles",
pk: id => Pk,
enums: { Status: [Draft="Draft", Published="Published"], },
{
title: text [required],
slug: text [unique],
body: richtext [required],
status: choice [enum(Status), default: "Draft"],
views: int [default: 0],
}
}
model! génère l'entité SeaORM (article::Model) et sa migration SQL (runique makemigrations) à partir de la même déclaration. Ajoutez #[form] et vous obtenez un formulaire type-safe correspondant, validé côté serveur et dérivable directement du schéma. Enregistrez la ressource dans admin! et le CRUD est déjà là — liste, recherche, filtres, permissions, tout y est :
admin! {
article: article::Model => ArticleForm {
title: "Articles",
list_display: [["title", "Title"], ["status", "Status"], ["views", "Views"]],
search_fields: ["title", "body"],
list_filter: [["status", "Status", 5]],
}
}
Pourquoi Runique
Rust a déjà de bonnes briques web, rapides et bas niveau — ce qui lui manque, c'est un framework offrant d'entrée la productivité quotidienne de Django. Assembler soi-même un ORM, un moteur de templates, une couche de formulaires et un admin est un projet à part entière avant même d'avoir écrit une seule fonctionnalité. Runique fait ce câblage à votre place, selon un jeu de conventions cohérent, pour que le temps aille dans votre application plutôt que dans sa plomberie — sans rien perdre de la sécurité des types ni des performances de Rust.
| Django (Python) | Runique (Rust) |
|---|---|
models.py | model! → entité SeaORM + migration |
forms.py | #[form] formulaires type-safe |
admin.py | admin! panel admin généré |
urls.py | urlpatterns! macro de routing |
| Templates Django | Tera (auto-échappé) |
| QuerySet | SeaORM + DSL de requêtes search! |
| middleware | slots de middleware ordonnés |
Pour le tableau complet : Runique vs Django.
Sécurité par défaut
Rien de tout ça n'est ajouté après coup — c'est la base dont vous partez :
- le CSRF compare les tokens en temps constant (
ct_eq), pour qu'aucun timing ne trahisse une correspondance - le CSP embarque un nonce par réponse, configurable via le builder
- le login est timing-safe (pas d'énumération d'utilisateurs par le temps de réponse), et les mots de passe sont hashés en Argon2
- les sessions sont persistées en base, avec priorité donnée aux sessions authentifiées quand la mémoire se tend
- les tokens de réinitialisation de mot de passe vivent en base, hashés SHA-256, à usage unique, durcis contre l'IDOR
- les sorties sont assainies (ammonia) en plus de l'auto-échappement de Tera, et la validation des hôtes autorisés est appliquée
Démarrage rapide
runique new myapp
cd myapp
cargo run # votre app est un binaire Rust normal
runique startrégénère le code CRUD admin depuis vos déclarationsadmin!, puis lancecargo runlui-même — une étape de génération one-shot enchaînée au lancement, pas un watcher en tâche de fond (voir Admin (bêta)). Un simplecargo runsaute la régénération.
Un main.rs allégé (version complète dans demo-app/src/main.rs) :
use runique::prelude::*;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let config = RuniqueConfig::from_env();
let db = DatabaseConfig::from_env()?.build().connect().await?;
RuniqueApp::builder(config)
.routes(url::routes())
.with_database(db)
.statics()
.build()
.await
.map_err(|e| -> Box<dyn std::error::Error> { Box::new(e) })?
.run()
.await?;
Ok(())
}
Les routes passent par la macro urlpatterns! et ressortent sous forme d'un Router Axum classique :
pub fn routes() -> Router {
urlpatterns! {
"/" => view!{ index }, name = "index",
"/blog/{id}" => view!{ blog_detail }, name = "blog_detail",
}
.rate_limit("/login", "login", view!(login_user), 10, 60, vec![Method::POST])
}
Pour le guide complet : Installation
Contenu de ce dépôt
runique/— le crate du framework lui-même, le produit et la source de véritédemo-app/— une vraie application construite contre le framework, utilisée pour le validerdocs/— documentation en anglais et en français
Version du workspace (source de vérité) : 2.2.0.
CLI
runique fournit :
runique new <name>runique start [--main src/main.rs] [--admin src/admin.rs]— régénère le code admin puis lance l'app (one-shot, pas un watcher)runique create-superuserrunique makemigrations --entities src/entities --migrations migration/src [--force false]runique migration up|down|status --migrations migration/src
⚠️ À propos du rollback de migrations
runique makemigrationsécrit les migrations en préservant l'ordre chronologique du système de migrations. Si vous devez un jour en revenir en arrière, passez plutôt par le CLI SeaORM : il garde la table de suivi des migrations synchronisée avec l'état réel du schéma. Mélanger les deux chemins de rollback peut désynchroniser ce suivi.
Admin (bêta)
runique start fait trois choses, dans l'ordre, sur un seul thread :
- il parse vos déclarations
admin!danssrc/admin.rs - il génère le code CRUD sous
src/admins/ - il lance
cargo run --release, bloquant
Il vérifie d'abord si .with_admin(...) existe dans src/main.rs, et ne génère/lance que si c'est le cas — sinon il quitte avec un message expliquant pourquoi. Pas de surveillance continue : relancez runique start pour régénérer après une modification de src/admin.rs.
C'est encore de la bêta : les permissions fonctionnent surtout au niveau des ressources pour l'instant, le dossier généré src/admins/ est écrasé à chaque régénération, et le durcissement est en cours plutôt que terminé.
Documentation admin : Admin
Features et bases de données
Activées par défaut : orm, all-databases.
Backends sélectionnables individuellement : sqlite, postgres, mysql, mariadb.
Sessions
CleaningMemoryStore remplace le MemoryStore par défaut : il ajoute un nettoyage automatique des sessions expirées, un système de double watermark (128 Mo / 256 Mo) pour borner la mémoire, et une priorité pour les sessions authentifiées — elles sont purgées en dernier sous pression, et survivent aux redémarrages grâce à un fallback en base.
Référence complète : Sessions
Tests et couverture
- Tests rapportés : 2375 réussis (2 ignorés)
- Snapshot de couverture (
2026-09-02, packagerunique, module admin inclus) : fonctions 75.54%, lignes 73.69%, régions 72.30%
cargo llvm-cov --package runique --summary-only
Détail complet par fichier : docs/couverture_test.md
Documentation
- Installation
- Architecture
- Configuration
- Routing
- Formulaires
- Modèle/Schéma
- Templates
- ORM
- Middlewares
- Messages flash
- Exemples
- Admin bêta
- Sessions
- Variables d'environnement
État du projet & ressources
- État du projet — tenu à jour au fil de l'avancement
- Changelog
- Runique vs Django — comparatif des fonctionnalités
- Crates.io
- Politique de sécurité
Licence
MIT — voir LICENSE