Lien avec les formulaires & enjeux techniques
Lien avec les formulaires via #[form(...)]
La macro attribut #[form(...)] attend :
schema = chemin_fonction(obligatoire)fields = [..](optionnel)exclude = [..](optionnel)
Elle génère uniquement :
- la struct avec
form: Forms impl ModelForm(schema(),fields(),exclude())
Le dev écrit ensuite impl RuniqueForm avec impl_form_access!(model) :
use runique::prelude::*;
#[form(schema = user_schema, fields = [username, email])]
pub struct UserForm;
impl RuniqueForm for UserForm {
impl_form_access!(model);
}
Avec validation métier (clean)
Overrider clean directement dans impl RuniqueForm — comme Django.
#[async_trait] est requis uniquement quand on override une méthode async :
#[form(schema = user_schema, fields = [username, email, password])]
pub struct RegisterForm;
#[async_trait]
impl RuniqueForm for RegisterForm {
impl_form_access!(model);
async fn clean(&mut self) -> Result<(), StrMap> {
let mut errors = StrMap::new();
if self.get_string("username").len() < 3 {
errors.insert("username".to_string(), "Minimum 3 caractères".to_string());
}
if !self.get_string("email").contains('@') {
errors.insert("email".to_string(), "Email invalide".to_string());
}
if errors.is_empty() { Ok(()) } else { Err(errors) }
}
}
is_valid()appelle automatiquementcleanaprès la validation structurelle. Les erreurs retournées sont attachées aux champs et affichées inline dans le template.
Enjeux techniques
Avantages
- Contrat unique modèle/schéma centralisé
- Génération cohérente migration + formulaire
- Réduction de duplication de définition de champs
cleanest l'override officiel du trait — uniforme entre formulaires manuels et basés modèle
Points d'attention
- DSL stricte : erreur de syntaxe = erreur de macro au build
fields/excludemal alignés avec le schéma => erreurs de génération/exécution#[async_trait]requis surimpl RuniqueFormuniquement quand on overridecleanouclean_field
Limitation connue — surcharge de champ non prise en charge
La surcharge individuelle d'un champ auto-généré par
#[form(...)]oumodel!n'est pas encore prise en charge.
Il n'est pas possible aujourd'hui de personnaliser un seul champ (ex: ajouter .max_size_mb(5) ou changer le label) sans réécrire l'intégralité de register_fields à la main, ce qui annule le bénéfice de la macro.
Contournement actuel : écrire un formulaire manuel complet et déclarer les champs explicitement.
// ❌ Pas encore possible
#[form(schema = article_schema)]
pub struct ArticleForm;
impl RuniqueForm for ArticleForm {
impl_form_access!(model);
// surcharger juste le champ image → impossible sans tout réécrire
}
// ✅ Contournement : formulaire manuel
impl RuniqueForm for ArticleForm {
impl_form_access!();
fn register_fields(form: &mut Forms) {
form.field(&TextField::text("titre").label("Titre").required());
form.field(
&FileField::image("image")
.upload_to("media/articles")
.max_size_mb(5),
);
}
}
Cette limitation sera levée en v2.0 avec la refactorisation du système de champs en widgets, qui permettra de déclarer et surcharger n'importe quel champ directement depuis le modèle.