Pour prendre un exemple concret, nous allons créer un site permettant de gérer des listes de souhaits, que nous appellerons \texttt{gwift} (pour \texttt{GiFTs\ and\ WIshlisTs} :)).
La première chose à faire est de définir nos besoins du point de vue de l'utilisateur, c'est-à-dire ce que nous souhaitons qu'un utilisateur puisse faire avec l'application.
Nous souhaitons développer un site où un utilisateur donné peut créer une liste contenant des souhaits et où d'autres utilisateurs, authentifiés ou non, peuvent choisir les souhaits à la réalisation desquels ils souhaitent participer.
L'utilisateur ayant créé une liste pourra envoyer un email directement depuis le site aux personnes avec qui il souhaite partager sa liste, cet email contenant un lien permettant d'accéder à cette liste.
Dans ce cas, le souhait pourrait aussi être subdivisé en plusieurs parties, de manière à ce que plusieurs personnes puissent participer à sa réalisation.
Un souhait pourrait aussi être réalisé plusieurs fois.
Pour gérer les utilisateurs, nous allons faire en sorte de surcharger ce que Django propose: par défaut, on a une la possibilité de gérer des utilisateurs (identifiés par une adresse email, un nom, un prénom, \ldots\hspace{0pt}) mais sans plus.
Ce qu'on peut souhaiter, c'est que l'utilisateur puisse s'authentifier grâce à une plateforme connue (Facebook, Twitter, Google, etc.), et qu'il puisse un minimum gérer son profil.
L'ORM de Django permet de travailler uniquement avec une définition de classes, et de faire en sorte que le lien avec la base de données soit géré uniquement de manière indirecte, par Django lui-même.
On peut schématiser ce comportement par une classe = une table.
Que s'il n'est pas spécifié, un identifiant \texttt{id} sera automatiquement généré et accessible dans le modèle.
Si vous souhaitez malgré tout spécifier que ce soit un champ en particulier qui devienne la clé primaire, il suffit de l'indiquer grâce à l'attribut \texttt{primary\_key=True}.
\item
Que chaque type de champs (\texttt{DateTimeField}, \texttt{CharField}, \texttt{UUIDField}, etc.) a ses propres paramètres d'initialisation.
Il est intéressant de les apprendre ou de se référer à la documentation en cas de doute.
La propriété \texttt{created\_at} est gérée automatiquement par Django grâce à l'attribut \texttt{auto\_now\_add}: de cette manière, lors d'un \textbf{ajout}, une valeur par défaut ("\textbf{maintenant}") sera attribuée à cette propriété.
\item
La propriété \texttt{updated\_at} est également gérée automatique, cette fois grâce à l'attribut \texttt{auto\_now} initialisé à \texttt{True}: lors d'une \textbf{mise à jour}, la propriété se verra automatiquement assigner la valeur du moment présent.
Cela ne permet évidemment pas de gérer un historique complet et ne nous dira pas \textbf{quels champs} ont été modifiés, mais cela nous conviendra dans un premier temps.
\item
La propriété \texttt{external\_id} est de type \texttt{UUIDField}.
Lorsqu'une nouvelle instance sera instanciée, cette propriété prendra la valeur générée par la fonction \texttt{uuid.uuid4()}.
\textbf{A priori}, chacun des types de champs possède une propriété \texttt{default}, qui permet d'initialiser une valeur sur une nouvelle instance.
permet de déclarer une relation 1-N entre deux classes.
% TODO : il y a des fautes de syntaxe dans
Dans la même veine, une relation 1-1 sera représentée par un champ de type `OneToOneField \textless{}\url{https://docs.djangoproject.com/en/1.8/topics/db/examples/one_to_one/\%3E\%60}\emph{,alors qu'une relation N-N utilisera un `ManyToManyField \textless{}\url{https://docs.djangoproject.com/en/1.8/topics/db/examples/many_to_many/\%3E\%60}}.
\item
L'attribut \texttt{default} permet de spécifier une valeur initiale, utilisée lors de la construction de l'instance.
Cet attribut peut également être une fonction.
\item
Pour rendre un champ optionnel, il suffit de lui ajouter l'attribut \texttt{null=True}.
\item
Comme cité ci-dessus, chaque champ possède des attributs spécifiques.
Le champ \texttt{DecimalField} possède par exemple les attributs \texttt{max\_digits} et \texttt{decimal\_places}, qui nous permettra de représenter une valeur comprise entre 0 et plus d'un milliard (avec deux chiffres décimaux).
\item
L'ajout d'un champ de type \texttt{ImageField} nécessite l'installation de \texttt{pillow} pour la gestion des images.
Nous l'ajoutons donc à nos pré-requis, dans le fichier \texttt{requirements/base.txt}.
La classe \texttt{User} référencée au début du snippet correspond à l'utilisateur qui sera connecté.
Ceci est géré par Django.
Lorsqu'une requête est effectuée et est transmise au serveur, cette information sera disponible grâce à l'objet \texttt{request.user}, transmis à chaque fonction ou \textbf{Class-based-view}.
C'est un des avantages d'un
framework tout intégré : il vient \textbf{batteries-included} et beaucoup de détails ne doivent pas être pris en compte.
Pour le moment, nous nous limiterons à ceci.
Par la suite, nous verrons comment améliorer la gestion des profils utilisateurs, comment y ajouter des informations et comment gérer les cas particuliers.
Pour chaque réalisation d'un souhait par quelqu'un, il est nécessaire de sauver les données suivantes, même si l'utilisateur n'est pas enregistré sur le site:
Cette adresse email sera unique dans notre base de données, pour ne pas créer une nouvelle occurence si un même utilisateur participe à la réalisation de plusieurs souhaits.