Comparatif

Comparatif Runique vs Django

CLI

CommandeDjangoRunique
Créer un projetdjango-admin startproject nomrunique new nom
Créer une apppython manage.py startapp nom
Migrations (générer)python manage.py makemigrationsrunique makemigrations
Migrations (appliquer)python manage.py migraterunique migration up
Migrations (annuler)python manage.py migrate app 0001runique migration down --files ...
Statut migrationsrunique migration status
Créer superuserpython manage.py createsuperuserrunique create-superuser
Démarrerpython manage.py runservercargo runrunique start pour (re)générer le panel admin

Routing

FonctionnalitéDjangoRunique
Déclaration des routesurls.py avec path()url.rs avec macro urlpatterns!{}
Routes dynamiquespath('users/<int:id>/', view)"/users/{id}" dans urlpatterns!
Namespacesapp_name + include()Router::new().nest("/prefix", ...)
Reverse URL{% url "nom_vue" %} natif{% link "nom_vue" %} → fonction Tera custom
Paramètre de chemin typékwargs['id'] (toujours str dans Django)request.get_path_as::<i32>("id")
Paramètre de chemin brutkwargs['id']request.get_path("id")
Query param uniquerequest.GET.get('key')request.get_query("key")
Query string complèterequest.GETrequest.query::<MyStruct>() (désérialise vers un struct Deserialize)
Headers HTTPrequest.META['HTTP_X_FOO']request.headers.get("x-foo")

Vues / Handlers

FonctionnalitéDjangoRunique
Vue fonctiondef ma_vue(request)async fn ma_vue(...)
Vue classeclass MaVue(View)
Accès sessionrequest.sessionrequest.session via context::template::Request
Accès DBModel.objects.get(...)Model::objects.get(...) ou builders SeaORM
Rendu templaterender(request, "template.html", ctx)request.render("template.html")
Redirectredirect("nom_url")Redirect::to("/url") ou reverse(&engine, "nom")
Messages flashmessages.success(request, "...")macros success!, error!, info!, warning!
Connexions secondairesDATABASES['mongo']engine.extension::<mongodb::Client>() (TypeMap multi-type)

Formulaires

FonctionnalitéDjangoRunique
Définitionclass MonForm(ModelForm)#[form] struct ou RuniqueForm manuel
Validationform.is_valid()form.is_valid().await
Champs disponiblesCharField, EmailField, FileField, etc.TextField, EmailField, PasswordField, HiddenField, ChoiceField, NumericField, BooleanField, FileField, DateField, TimeField, DateTimeField, DurationField, PhoneField
Rendu HTML{{ form.as_p }}{% form.nom_form %} (entier) ou {% form.nom_form.champ %}
CSRF intégréautomatiqueautomatique — injecté avant le premier champ
Sauvegardeform.save()form.save(&db).await (si #[form])
Accès aux donnéesform.cleaned_data['clé']form.cleaned_string("clé"), form.cleaned_i32(...), etc.
Validation asyncnonoui (accès DB dans clean())
Validation croiséeclean()clean() async
FichiersFileFieldFileField multipart natif avec validation type/taille
Sanitisation HTMLnon (à la main)sanitize_rich / sanitize_strict appliquées aux champs richtext

Templates

FonctionnalitéDjangoRunique
MoteurDjango Template LanguageTera (syntaxe Jinja2 / Django-like)
Héritage{% extends %} / {% block %}idem
Fichiers statiques{% load static %} + {% static "file" %}{% static "file" %} natif
Fichiers media{{ MEDIA_URL }}file{% media "file" %} natif (variables supportées)
URL reverse{% url "nom" %}{% link "nom" %}
CSRF{% csrf_token %}{% csrf %}
Messages{% for m in messages %}{% messages %}
Internationalisation{% trans "..." %}{{ t("section.clé") }} / {{ tf("...", ["var"]) }}

ORM / Base de données

FonctionnalitéDjangoRunique
ORMDjango ORM natifSeaORM (Rust async)
Définition modèleclass User(models.Model)macro model!{} (types v1 SQL ou v2 sémantiques)
Migrations autooui (détection changements)runique makemigrations
QuerySet chaînableUser.objects.filter(...).order_by(...)User::objects.filter(...).order_by(...)
.get() strictlève MultipleObjectsReturned.one() — retourne Err si plusieurs lignes
Tri aléatoireorder_by('?').order_by_random()
Tri par expression.order_by_expr(expr, order)
RelationsForeignKey, ManyToMany, OneToOneRelations SeaORM standard
Transactionswith transaction.atomic()db.transaction(...)
Multi-moteur SQLouiPostgreSQL, MySQL, SQLite
Connexions secondairesDATABASES multi-entrées.with_custom_db::<T>() × N types (TypeMap)
Extension table frameworkextend!{}ALTER TABLE ADD COLUMN sur tables eihwaz_*

Authentification

FonctionnalitéDjangoRunique
Login / Logoutauthenticate() + login()auth_login(...), logout()
Vérif authentificationrequest.user.is_authenticatedis_authenticated(&session).await
Utilisateur courantrequest.userCurrentUser (injecté via middleware)
Protection route@login_requiredif !is_authenticated(...).await { redirect }
Sessionsnatiftower-sessions (MemoryStore + DB fallback)
Protection brute forcedjango-axes (tiers)LoginGuard natif (lockout auto)
Hashage mot de passePBKDF2 / Argon2Argon2 par défaut
Reset passwordnatifnatif — template email personnalisable via .email_template("...")
Déconnexion forcéeouiRuniqueSessionStore::invalidate_all(user_id)

Sécurité

FonctionnalitéDjangoRunique
CSRFnatifnatif (comparaison constant-time)
CSPdjango-csp (tiers)natif (use_nonce: true par défaut)
HSTSSECURE_HSTS_SECONDSnatif
SameSite cookiesconfigurableStrict par défaut
HttpOnly cookiespar défauttoujours true
Rate limitingdjango-ratelimit (tiers)RateLimiter natif
Open Redirectnatif — toutes les réponses 3xx vérifiées (slot 25)
CORSdjango-cors-headers (tiers)natif via .with_cors(...)
Permissions-Policynatif — preset sécurisé par défaut
Trusted Proxies / XFFSECURE_PROXY_SSL_HEADER (partiel)natif — validation chaîne XFF complète, preset RFC 1918
Secret keymanuelgénérée auto à runique new

Panel Admin

FonctionnalitéDjangoRunique
Activationadmin.site.register(Model)macro admin!{}
CRUD completnatifnatif
Pagination listenatif.page_size(n) (liste + historique)
list_displaynatiflist_display: [["col", "Libellé"], ...]
Résolution FK en liste3ème élément : ["fk_id", "Libellé", "table.colonne"]
Recherche / filtresnatiflist_filter + recherche plein-texte SQL — colonnes directes uniquement, filtres non cumulables (UI)
Actions de groupeactionsgroup_action — bool (2 éléments) ou enum (3 éléments, valeur exacte)
Création multiplebulk_create: champ — split par virgule, insère N enregistrements
Édition en massebulk edit natif sur sélection multi-entrées
Relations M2Mfilter_horizontal / ManyRelatedFieldm2m: [...] — table de jonction, diff automatique
Routes admin customget_urls().extra_routes(vec![...])
Templates customouioui (hiérarchie Tera)
Permissionspar ressourceRBAC dynamique (Groupes / Droits scopés)
Historique modificationsdjango-simple-history (tiers)historique natif (créé/modifié/supprimé) avec diff de champs
Configuration builtinsbloc configure {} dans admin!{}
Verrouillage optimistenatif — détecte les éditions concurrentes (__original_updated_at)
Protection brute-force logindjango-axes (tiers)natif — LoginGuard + rate limiter sur le login admin
Email création compteplugin tiersnatif — inject_password: true génère mot de passe temporaire + email
Rafraîchissement liste partielnatif — list_partial HTMX sans rechargement page
Fieldsetsfieldsets
Champs lecture seulereadonly_fields
Navigation par datedate_hierarchy
ExportCSV natif
Boutons save avancés"Save and continue" / "Save and add"

Email

FonctionnalitéDjangoRunique
Envoi emailsend_mail() natifEmail::new().send() natif
Templates emailnatiftemplates Tera via .template("emails/mon.html")
Backend SMTPconfigurableconfiguration via .env
Backend dev (console)EMAIL_BACKEND = 'console'EMAIL_BACKEND=console dans .env

Internationalisation

FonctionnalitéDjangoRunique
Langues supportéesillimitées9 langues par défaut (JSON compilé)
Fallbackouioui (Lang::En)
Traduction_("...")t("section.clé") / tf("...", ["var"])

Performance & Déploiement

AspectDjangoRunique
RuntimeCPython (interprété)Tokio async Rust (compilé)
Empreinte mémoire~50–100 MB~5–15 MB
Compilationbinaire statique unique
ACME / TLS autocertbot (externe)natif via feature acme

Ce qu'il manque encore (comparé à Django)

  • Redimensionnement automatique d'images : resize/cropping côté serveur non natif.
  • Vues CRUD publiques génériques : pas d'équivalent aux DetailView, ListView, CreateView de Django pour les vues publiques — prévu via crud!{} (en développement). Le panel admin couvre le CRUD backoffice via admin!{}.
  • Signals / hooks modèles : before_save, after_save, before_delete, after_delete — infrastructure posée, générateur en cours de branchement.
  • Management commands : pas d'équivalent à manage.py custom_command — les opérations one-shot passent par src/bin/.
  • Test client intégré : pas de client HTTP de test natif — utiliser reqwest ou axum::test.
  • Fixtures : pas de loaddata/dumpdata — les seeds sont des fonctions Rust.
  • Admin inline : pas d'édition d'objets liés directement dans le formulaire parent.
  • Admin filtres cumulables : cliquer une valeur de filtre réinitialise les autres colonnes filtrées — le backend supporte plusieurs filtres simultanés (Vec), mais les liens générés dans le template ne préservent pas les filtres des autres colonnes.
  • Admin filtre FK : list_filter ne supporte que les colonnes directes — pas de traversée de relation (article__auteur__nom).
  • Admin fieldsets : pas de groupement de champs par section dans les formulaires admin (fieldsets Django).
  • Admin readonly fields : pas de readonly_fields — les champs non éditables doivent être exclus du formulaire.
  • Admin navigation par date : pas de date_hierarchy pour filtrer la liste par année/mois/jour.
  • Admin export : pas d'export CSV/JSON natif depuis la liste.
  • Admin boutons save avancés : pas de "Enregistrer et continuer" / "Enregistrer et ajouter un autre".
  • i18n complète : t()/tf() disponibles, mais pas de pluralisation ni de traduction des templates Tera.
  • Sitemap / RSS : non natif.
  • Authentification tiers : OAuth / OIDC structuré (Google, Microsoft, Apple, LDAP, SAML) mais flow non implémenté — stub uniquement. JWT et API key auth absents.
  • Observabilité sécurité : CSP report-uri/report-to absent — les violations ne sont pas collectées. Audit log des connexions (réussies/échouées/lockouts) non tracé en DB.