Création d'un fichier forms.py
dans le dossier de l'application, et ajout d'une class qui hérite de ModelForm
cette classe pourrait aussi être créée dans le fichier `models.py` mais par convention, on met le code des formulaires dans le fichier `forms.py`
from django import forms from .models import Article #... class ArticleForm(forms.ModelForm): class Meta: model = Article fields = ['title', 'content', 'is_draft', 'categories'] labels = { 'title': 'Titre' } help_texts = { 'title': 'Veuillez saisir un titre' }
La plupart du temps, les formulaires correspondent étroitement avec les modèles Django. Les champs étant déjà définis au niveau du modèle, il est inutile de les redéfinir pour créer le formulaire.
fields
permet de choisir les champs que l'on veut afficher dans le formulaire.
labels
et help_texts
permettent de surcharger les labels et d'ajouter un texte d'aide si besoin.
Exemple de fichier add_article.html
<form action="" method="post"> {% csrf_token %} {{ form }} <input type="submit" value="Submit"> </form>
La balise form
permet d'afficher le formulaire qui est passé au gabarit. Cela va créer automatiquement les balises label
et input
.
form
peut prendre trois options afin de configurer l'affichage que l'on souhaite :
form.as_table
affiche les composants sous forme de cellules de tableau à l’intérieur de balises <tr>form.as_p
affiche les composants dans des balises <p>form.as_ul
affiche les composants dans des balises <li>
{% csrf_token %}
permet de protéger le formulaire contre la faille CSRF (Cross-Site Request Forgery). Voir cet article pour davantage d'informations.
Il est également possible d'afficher manuellement les champs, voir la documentation Affichage manuel des champs
Les données de formulaire renvoyés sont traitées par une vue (views.py
), en principe la même qui a servi à produire le formulaire. Cela permet de réutiliser une partie de la même logique.
On utilise request.method
pour savoir si la requête a été faire en GET
ou en POST
from django.shortcuts import render, redirect from .models import Article from .forms import ArticleForm #... def add_article(request): # Si requête POST, le formulaire a été soumis if request.method == 'POST': form = ArticleForm(request.POST) # Validation des données if form.is_valid(): form.save() # Redirige vers une page de confirmation par exemple return redirect('confirm-article') # Si requête, on crée un formulaire vierge else: form = ArticleForm() return render(request, 'blogue/add_article.html', {'form': form}) def confirm_article(request): return render(request, 'blogue/confirm_article.html')
Vous devez créer un fichier confirm_article.html
avec un message de confirmation par exemple…
Si form.is_valid()
est False
, l'objet form
est renvoyé au gabarit avec les erreurs afin de les afficher automatiquement.
Pour finir, il faut définir les routes correspondantes dans le fichier urls.py
from django.urls import path from . import views urlpatterns = [ #... path('add-article/', views.add_article, name='addArticle'), path('confirm-article/', views.confirm_article, name='confirm-article') ]
Reprenons le fichier forms.py
.
from django import forms #... class CategoryForm(forms.Form): title = forms.CharField(max_length=255, label = "Titre") description = forms.CharField(widget=forms.Textarea, help_text = "Saisir une description")
Documentation des types de champs.
En utilisant Form
à la place de ModelForm
, on doit saisir chaque champ de formulaire.
Dans views.py
, il faut enregistrer l'objet grâce à la méthode objects.create
.
Avant d'enregistrer, il faut utiliser la méthode .cleaned_data
afin de “nettoyer” les données. Django va par exemple convertir les types pour les enregistrer correctement dans la base de données.
def add_category(request): if request.method == 'POST': form = CategoryForm(request.POST) if form.is_valid(): title = form.cleaned_data['title'] description = form.cleaned_data['description'] Category.objects.create(title=title, description=description) return redirect('confirm-category') # Si requète GET, on crée un formulaire vierge else: form = CategoryForm() return render(request, 'blogue/add_category.html', {'form': form})
En plus de la validation automatique, on peut ajouter nos propres validations dans forms.py
Exemple :
class CategoryForm(forms.Form): title = forms.CharField(max_length=255, label = "Titre") description = forms.CharField(widget=forms.Textarea, help_text = "Saisir une description") num = forms.DecimalField(max_digits=10, decimal_places=2) def clean_num(self): data = self.cleaned_data['num'] if data < 0: raise forms.ValidationError("Veuillez saisir un nombre > 0") return data def clean_title(self): data = self.cleaned_data['title'] if data == "chat": raise forms.ValidationError("Il y a déjà trop de chats sur Internet !") return data