\chapter{Forms}

\includegraphics{images/xkcd-327.png}

\begin{quote}
    Le form, il s'assure que l'utilisateur n'a pas encodé de conneries et que l'ensemble reste cohérent.
    Il (le form) n'a pas à savoir que tu as implémenté des closure tables dans un graph dirigé acyclique.
\end{quote}

Ou comment valider proprement des données entrantes.

Quand on parle de \texttt{forms}, on ne parle pas uniquement de formulaires Web.
% TODO: tu as une explication (:) dans une explication (:). Je trouve pas ca très français.
On pourrait considérer qu'il s'agit de leur objectif principal, mais on peut également voir un peu plus loin : on peut en fait voir les \texttt{forms} comme le point d'entrée pour chaque donnée arrivant dans notre application : il s'agit en quelque sorte d'un ensemble de règles complémentaires à celles déjà présentes au niveau du modèle.

L'exemple le plus simple est un fichier \texttt{.csv} : la lecture de ce fichier pourrait se faire de manière très simple, en récupérant les valeurs de chaque colonne et en l'introduisant dans une instance du modèle.

Mauvaise idée.
On peut proposer trois versions d'un même code, de la version simple (lecture du fichier csv et jonglage avec les indices de colonnes), puis une version plus sophistiquée (et plus lisible, à base de \href{https://docs.python.org/3/library/csv.html\#csv.DictReader}{DictReader}), et la version + à base de form.

Les données fournies par un utilisateur \textbf{doivent} \textbf{toujours} être validées avant introduction dans la base de données.
Notre base de données étant accessible ici par l'ORM, la solution consiste à introduire une couche supplémentaire de validation.

Le flux à suivre est le suivant:

\begin{enumerate}
    \item Création d'une instance grâce à un dictionnaire
    \item Validation des données et des informations reçues
    \item Traitement, si la validation a réussi.
\end{enumerate}

Ils jouent également deux rôles importants:

\begin{enumerate}
    \item Valider des données, en plus de celles déjà définies au niveau du modèle
    \item Contrôler le rendu à appliquer aux champs.
\end{enumerate}

Ils agissent come une glue entre l'utilisateur et la modélisation de vos structures de données.

\section{Flux de validation}

\textbar{} .Validation \textbar{} .is\_valid \textbar{} .clean\_fields ↓
.clean\_fields\_machin

A compléter ;-)

\section{Dépendance avec le modèle}

Un \textbf{form} peut dépendre d'une autre classe Django.
Pour cela, il suffit de fixer l'attribut \texttt{model} au niveau de la \texttt{class\ Meta} dans la définition.

\begin{minted}{python}
from django import forms

from wish.models import Wishlist


class WishlistCreateForm(forms.ModelForm):
    class Meta:
        model = Wishlist
        fields = ('name', 'description')
\end{minted}

% TODO: je comprends pas pourquoi il y a autant de \ dans le paragraphe.
De cette manière, notre form dépendra automatiquement des champs déjà déclarés dans la classe \texttt{Wishlist}.
Cela suit le principe de \texttt{DRY\ \textless{}don’t\ repeat\ yourself\textgreater{}\textasciigrave{}\_,\ et\ évite\ qu’une\ modification\ ne\ pourrisse\ le\ code :\ en\ testant\ les\ deux\ champs\ présent\ dans\ l’attribut\ \textasciigrave{}fields}, nous pourrons nous assurer de faire évoluer le formulaire en fonction du modèle sur lequel il se base.

\section{Rendu et affichage}

Le formulaire permet également de contrôler le rendu qui sera appliqué lors de la génération de la page.
Si les champs dépendent du modèle sur lequel se base le formulaire, ces widgets doivent être initialisés dans
l'attribut \texttt{Meta}.
Sinon, ils peuvent l'être directement au niveau du champ.

\subsection{Squelette par défaut}

On a d'un côté le \{\{ form.as\_p \}\} ou \{\{ form.as\_table \}\}, mais il y a beaucoup mieux que ça ;-) Voir les templates de Vitor et en passant par \texttt{widget-tweaks}.

\subsection{Crispy-forms}

Comme on l'a vu à l'instant, les forms, en Django, c'est le bien.
Cela permet de valider des données reçues en entrée et d'afficher (très) facilement des formulaires à compléter par l'utilisateur.

Par contre, c'est lourd.
Dès qu'on souhaite peaufiner un peu l'affichage, contrôler parfaitement ce que l'utilisateur doit remplir, modifier les types de contrôleurs, les placer au pixel près, \ldots\hspace{0pt} Tout ça demande énormément de temps.
Et c'est là qu'intervient \href{http://django-crispy-forms.readthedocs.io/en/latest/}{Django-Crispy-Forms}.
Cette librairie intègre plusieurs frameworks CSS (Bootstrap, Foundation et uni-form) et permet de contrôler entièrement le \textbf{layout} et la présentation.

(c/c depuis le lien ci-dessous)

Pour chaque champ, crispy-forms va :

\begin{itemize}
    \item
        utiliser le \texttt{verbose\_name} comme label.
    \item
        vérifier les paramètres \texttt{blank} et \texttt{null} pour savoir si le champ est obligatoire.
    \item
        utiliser le type de champ pour définir le type de la balise \texttt{\textless{}input\textgreater{}}.
    \item
        récupérer les valeurs du paramètre \texttt{choices} (si présent) pour la balise \texttt{\textless{}select\textgreater{}}.
\end{itemize}

\url{http://dotmobo.github.io/django-crispy-forms.html}

\section{Conclusions}

Toute donnée entrée par l'utilisateur \textbf{doit} passer par une instance de \texttt{form}.
