> Modules non standards > Django pour le développement web > Forms
Forms
Forms simples
Le principe est de définir une classe représentant le contenu d'une form (formulaire) html qui héritent de classe forms.Form :
- exemple avec une form à 2 champs :
from django import forms
class MyForm(forms.Form):
label = forms.CharField(label = 'Label', max_length = 5)
description = forms.CharField(label = 'Description', max_length = 100, required = False)
- label est le nom qui apparaît dans le formulaire et aussi dans l'attribut name du tag input.
- utiliser required = False pour indiquer que le champ est optionnel lors du remplissage (sinon, par défaut, il est obligatoire).
- l'objet form ne génère que les champs, pas les tags de la forme (<form>) ni le submit !
- pour remplir certains champs à la construction : form = MyForm(initial = {'label': 'valeur'})
- utilisation typique d'un objet Form dans une view :
- attention : c'est la même fonction view qui présente la forme initiale, la forme remplie en cas d'erreur ou qui effectue le traitement des données soumises.
- en cas d'erreur, l'objet Form est retourné rempli et donc, on peut le réutiliser pour représenter la form remplie à corriger.
- une fois que form soumise est valide, les valeurs sont transférées dans le champ cleaned_data qui est un dictionnaire.
def create(request):
if request.method == 'POST':
# si c'est une soumission de la form
form = MyForm(request.POST)
if form.is_valid():
# on execute seulement si tout est ok dans la form
myObj = MyObj() # Definition d'un objet modele
myObj.label = form.cleaned_data['label']
myObj.description = form.cleaned_data['description']
return HttpResponseRedirect('/bravo') # Redirection vers une url
else:
# generation de la form initialement vide
form = MyForm()
# retour de la form, soit vide, soit remplie mais avec une erreur, avec un template
return render(request, 'create.html', {'form': form})
- côté template (ici create.html) :
- l'url de l'action n'est pas mise en dure.
- il faut mettre les tags form et input de type submit.
- on peut choisir de formatter la form comme table (form.as_table), comme liste (form.as_ul) ou comme paragraphes (form.as_p).
<form action="{% url myApp:createUrl' %}" method="post">
{% csrf_token %}
<table>
{{ form.as_table }}
</table>
<div class="submit"><input type="submit" name="Créer"></div>
</form>
- on peut mettre les objets Form où l'on veut, comme par exemple dans un fichier forms.py (totalement libre).
Validation
Validation des champs d'un Form à la soumission : elle est déclenchée quand on appelle
is_valid() sur la Form, et il y a de multiples possibilités :
- d'abord, appel de la fonction validate de chaque champ : on peut la surcharger de la façon suivante en affectant une fonction à l'attribut validate qui doit lever l'exception ValidationError si le champ n'est pas bon :
from django.core.exceptions import ValidationError
class MyForm(forms.Form):
label = forms.CharField(label = 'Label', max_length = 5)
def myValidationFunction(value):
...
raise ValidationError('my message')
label.validate = myValidationFunction
- puis appel des fonctions validator que l'on définit avec le tag validators et qui doivent aussi l'exception ValidationError si le champ n'est pas bon :
from django.core.exceptions import ValidationError
class MyForm(forms.Form):
def myValidationFunction(value):
sys.stderr.write('called validateLabel\n')
if re.search('^[A-Z]+\d+$', value) is None:
raise ValidationError('Format should be [A-Z]+\d+')
label = forms.CharField(label = 'Label', max_length = 5, validators = [validateLabel])
- puis, les champs sont transférés dans le dictionnaire cleaned_data.
- puis, appel de la méthode clean_<nomChamp>. Cette fonction doit renvoyer le champ modifié ou non :
class MyForm(forms.Form):
label = forms.CharField(label = 'Label', max_length = 5)
def clean_label(self):
return self.cleaned_data['label'].strip()
- enfin, appel de la méthode clean à la fin qui permet de traiter l'ensemble des champs de la forme, par exemple si interactions entre les champs :
class MyForm(forms.Form):
def clean(self):
...
ModelForms
Avec les Forms ci-dessus, on se retrouve souvent à recopier les champs de la form dans les champs du modèle quand la form correspond exactement à un modèle. Pour éviter cela, on peut utiliser les ModelForms.
ModelForm :
- on définit une classe qui hérite de ModelForm et indique le modèle utilisé, ainsi que les champs à présenter :
from django.forms import ModelForm
class MyForm(ModelForm):
class Meta:
model = MyModel
fields = ['label', 'description']
- puis dans la view, on utilise ce ModelForm sans avoir besoin de recopier les champs dans le modèle et on peut directement utiliser save :
def create(request):
if request.method == 'POST':
# si c'est une soumission de la form
form = MyForm(request.POST)
if form.is_valid():
form.save()
return HttpResponseRedirect('/bravo')
else:
# generation de la form initialement vide
form = MyForm()
# retour de la form, soit vide, soit remplie mais avec une erreur, avec un template
return render(request, 'create.html', {'form': form})
- on peut indiquer que tous les champs doivent être inclus en mettant fields = '__all__'.
- on peut préciser certains champs (en reprenant le même nom que dans le modèle), avec par exemple le widget à utiliser :
class MyForm(ModelForm):
label = CharField(label = 'Label', max_length = 5, \
validators = [validateLabel], widget = TextInput(attrs = {'size': 5}))
class Meta:
model = MyModel
fields = '__all__'
Copyright python-simple.com
programmer en python, tutoriel python, graphes en python, Aymeric Duclert