From aa92bc94670f0b03d14c33c0254aa148c08ba2c8 Mon Sep 17 00:00:00 2001 From: Skia Date: Sun, 19 Jun 2016 21:16:04 +0200 Subject: [PATCH] Update report --- doc/TW_Skia/Makefile | 4 +- doc/TW_Skia/Rapport.tex | 186 +++++++++++++++++++++++++++++++++------- 2 files changed, 156 insertions(+), 34 deletions(-) diff --git a/doc/TW_Skia/Makefile b/doc/TW_Skia/Makefile index ae01698b..4d77f84b 100644 --- a/doc/TW_Skia/Makefile +++ b/doc/TW_Skia/Makefile @@ -4,8 +4,8 @@ all: rapport clean rapport: Rapport.tex @echo "Compiling "$< - $(CC) $< - $(CC) $< + $(CC) -shell-escape $< + $(CC) -shell-escape $< clean: @echo "Cleaning folder" diff --git a/doc/TW_Skia/Rapport.tex b/doc/TW_Skia/Rapport.tex index 05976dbf..e7258dd5 100644 --- a/doc/TW_Skia/Rapport.tex +++ b/doc/TW_Skia/Rapport.tex @@ -18,7 +18,7 @@ \usepackage{fancyhdr} %Options: Sonny, Lenny, Glenn, Conny, Rejne, Bjarne, Bjornstrup \usepackage[Bjornstrup]{fncychap} -\usepackage[procnames]{listings} +\usepackage{minted} \usepackage[colorlinks=true,linkcolor=black]{hyperref} \usepackage{pdfpages} \usepackage{titlesec, blindtext, color} @@ -47,29 +47,17 @@ \definecolor{darkgreen}{RGB}{0,130,0} \definecolor{gray}{RGB}{100,100,100} -\lstset{ - language=Python, - basicstyle=\ttfamily\small, - morekeywords={True,False}, - morestring=[s][\color{darkgreen}]{r'}{'}, - morestring=[s][\color{brown}]{"""}{"""}, - numbers=left, - numberstyle=\color{gray}, - keywordstyle=\color{keywords}, - commentstyle=\color{comments}, - stringstyle=\color{green}, - showstringspaces=false, -} %inner meta \title{Architecture de Sith: le nouveau site AE} \author{Skia (Florent JACQUET)} -\date{\today} +\date{Dernière version: \today} \begin{document} +\maketitle + \tableofcontents -\listoffigures \chapter*{Introduction} \addcontentsline{toc}{chapter}{Introduction} @@ -89,12 +77,12 @@ l'intégralité des fonctions liées à l'argent, qui sont les plus critiques. \par C'est là un des choix les plus important lors d'un tel projet, puisqu'il se fait au début, et qu'il n'est ensuite plus possible de revenir en arrière. Le PHP vieillissant, et piègeux\footnote{\url{https://eev.ee/blog/2012/04/09/php-a-fractal-of-bad-design/}} a donc été mis de côté au profit -d'un language plus stable, le Python dans sa version 3. +d'un language plus stable, le \emph{Python} dans sa version 3. \section{Python3} \label{sec:python3} -\par Le site étant développé en Python, il est impératif d'avoir un environnement de développement approprié à ce -language. L'outil \verb#virtualenv# permet d'installer un environnement Python de manière locale, sans avoir besoin des +\par Le site étant développé en \emph{Python}, il est impératif d'avoir un environnement de développement approprié à ce +language. L'outil \verb#virtualenv# permet d'installer un environnement \emph{Python} de manière locale, sans avoir besoin des droits root pour installer des packages. De plus cela permet d'avoir sur sa machine plusieurs environnements différents, adaptés à chaque projet, avec chacun des versions différentes des même paquets. \par La procédure pour installer son \verb#virtualenv# est décrite dans le fichier \verb#README# situé à la racine du @@ -102,20 +90,20 @@ projet. \section{Django} \label{sec:django} -\par Django est un framework web pour Python, apparu en 2005, et fournissant un grand nombre de fonctionnalités pour +\par \emph{Django} est un framework web pour \emph{Python}, apparu en 2005, et fournissant un grand nombre de fonctionnalités pour développer un site rapidement et simplement. Cela inclut entre autre un serveur Web, pour les échanges HTTP, un parseur d'URL, pour le routage des différentes URI du site, un ORM\footnote{Object-Relational Mapper} pour la gestion de la base de donnée, ou encore un moteur de template, pour les rendus HTML. -\par La version 1.8 de Django a été choisie pour le développement de ce projet, car c'est une version LTS (Long Term +\par La version 1.8 de \emph{Django} a été choisie pour le développement de ce projet, car c'est une version LTS (Long Term Support), c'est à dire qu'elle restera stable et maintenue plus longtemps que les autres (au moins jusqu'en Avril 2018). \par La documentation est disponible à cette addresse: \url{https://docs.djangoproject.com/en/1.8/}. Bien que ce rapport -présente dans les grandes lignes le fonctionnement de Django, il n'est pas et ne se veut pas exhaustif, et la +présente dans les grandes lignes le fonctionnement de \emph{Django}, il n'est pas et ne se veut pas exhaustif, et la documentation restera donc toujours la référence à ce sujet. \subsection{Le fichier de management et l'organisation d'un projet} \label{sub:Le fichier de management et l'organisation d'un projet} -\par Lors de la création d'un projet Django, plusieurs fichiers sont créés. Ces fichiers sont essentiels pour le projet, +\par Lors de la création d'un projet \emph{Django}, plusieurs fichiers sont créés. Ces fichiers sont essentiels pour le projet, mais ne contiennent en général pas de code à proprement parler. Ce n'est pas là qu'on y développe quoi que ce soit. \subsubsection{manage.py} @@ -126,7 +114,7 @@ elles: \begin{itemize} \item \textbf{startapp} \\ Créer une application - \item \textbf{makemigration} \\ + \item \textbf{makemigrations} \\ Parser les modèles pour créer les fichiers de migration de la base de donnée \item \textbf{migrate} \\ Appliquer les migrations sur la base de données @@ -139,15 +127,62 @@ elles: \par Un premier dossier est toujours créé, du nom du projet, et contenant plusieurs fichiers: \verb#settings.py#, \verb#urls.py#, et \verb#wsgi.py#. +\par \verb#settings.py# est un fichier \emph{Python} servant à définir un grand nombre de constantes paramètrant le +fonctionnement du site. L'avantage par rapport à un fichier de configuration classique est que ce dernier est +executable, et on peut donc y mettre de la logique, afin d'avoir des paramètres dynamiques. + +\par \verb#urls.py# est le fichier principale contenant les routes du site, c'est à dire les URLs existantes. Il se +charge en général d'inclure les fichiers \verb#urls.py# de chaque application afin de garder une architecture modulaire +et simple. + +\par \verb#wsgi.py# contient quant à lui les paramètres pour la mise en production du site en tant qu'application WSGI +(Web Server Gateway Interface) pour tourner derrière un serveur Web. + +\subsection{Organisation d'une application} +\label{sub:organisation_d_une_application} +\par Lorsque l'on créer une application avec \verb#./manage.py startapp#, on obtient une fois de plus un dossier type. +On trouve dans celui-ci un certain nombre de fichiers: +\begin{itemize} + \item \textbf{\_\_init\_\_.py} \\ + Permet de définir le dossier comme un package \emph{Python}. Ce fichier est généralement vide. + \item \textbf{models.py} \\ + C'est là qu'on définit tous les modèles, c'est à dire toutes les classes qui définissent des tables dans la base + de donnée. + \item \textbf{views.py} \\ + Les vues y sont définies. + \item \textbf{admin.py} \\ + C'est là que l'on déclare quels modèles doivent apparaîtrent dans l'interface fournie par le module + d'administration. + \item \textbf{tests.py} \\ + Ce dernier fichier sert à écrire les tests fonctionnels ou unitaires à l'aide de la librairie de test de \emph{Django}. + \item \textbf{migrations} \\ + Ce dossier sert à stocker les fichiers de migration de la base de donnée générés par \verb#./manage.py makemigrations#. +\end{itemize} +\vskip 1em +\par On rajoute par la suite généralement plusieurs fichiers: +\begin{itemize} + \item \textbf{urls.py} \\ + Pour y définir toutes les URLs de l'application, et ensuite inclure ce fichier dans le fichier \verb#urls.py# + global au projet. + \item \textbf{templates} \\ + Celui-ci est un dossier, et on y remet en général un sous dossier du nom de l'application afin de s'en servir de + namespace pour les templates. +\end{itemize} +\vskip 1em +\par Dans le cas où un fichier \emph{Python} deviendrait trop gros ou trop complexe, il est toujours possible de le diviser en +plusieurs fichiers que l'on met dans un dossier du même nom que ce fichier de départ, et contenant en plus un fichier +\verb#__init__.py#. De plus, pour faciliter les imports depuis ce dossier, on peut mettre dans \verb#__init__.py# la +ligne\footnote{Un exemple est disponible dans l'application core}: +\mint{python}|from .[nom_de_fichier_sans_le_.py] import *| \subsection{Les modèles avec l'ORM} \label{sub:les_modèles_avec_l_orm} \subsubsection{Le modèle en lui même} \label{ssub:Le modèle en lui même} -\par Rien ne vaudra un bon exemple pour comprendre comment sont construits les modèles avec Django: +\par Rien ne vaudra un bon exemple pour comprendre comment sont construits les modèles avec \emph{Django}: \begin{addmargin}[-7em]{0em} -\begin{lstlisting} + \begin{minted}{python} class Club(models.Model): # (1) """ The Club class, made as a tree to allow nice tidy organization @@ -172,7 +207,7 @@ class Club(models.Model): # (1) default=settings.SITH_GROUPS['root']['id']) # (7) edit_groups = models.ManyToManyField(Group, related_name="editable_club", blank=True) # (8) view_groups = models.ManyToManyField(Group, related_name="viewable_club", blank=True) -\end{lstlisting} +\end{minted} \end{addmargin} \par Explications: \begin{description} @@ -183,18 +218,18 @@ class Club(models.Model): # (1) donnée une fois que \verb#./manage.py migrate# a été appliqué. \item[(4)] Une \verb#ForeignKey#, l'une des relations les plus utilisée. \verb#related_name# précise le nom qui sert de retour vers cette classe depuis la classe pointée. Ici, elle est même récursive, puisque l'on pointe vers la - classe que l'on est en train de définir, ce qui donne au final une structure d'arbre. - \item[(5)] On peut toujours préciser des \verb#validators#, afin que le modèle soit contraint, et que Django + classe que l'on est en train de définir, ce qui donne au final une structure d'arbre.)r + \item[(5)] On peut toujours préciser des \verb#validators#, afin que le modèle soit contraint, et que \emph{Django} maintienne toujours des informations cohérentes dans la base. \item[(6)] Un message d'erreur peut être précisé pour expliciter à l'utilisateur les problèmes rencontrés. \item[(7)] On utilise ici le champ \verb#default# pour préciser une valeur par défaut au modèle, et celui-ci est - affecté à une valeur contenue dans les \verb#settings# de Django. + affecté à une valeur contenue dans les \verb#settings# de \emph{Django}. \item[(8)] Les \verb#ManyToManyField# permettent de générer automatiquement une table intermédiaire de manière transparente afin d'avoir des relations doubles dans les deux classes mises en jeu. \item[OneToOneField] Il n'est pas présent dans ce modèle, mais est très utilisé pour étendre une table avec des informations supplémentaires sans toucher à la table originale. \item[PRIMARY KEY] Les plus observateurs d'entre vous auront remarqué qu'il n'y a pas ici de \verb#PRIMARY KEY# de précisé. En - effet, Django s'en occupe automatiquement en rajoutant un champ \verb#id# jouant ce rôle. On peut alors y + effet, \emph{Django} s'en occupe automatiquement en rajoutant un champ \verb#id# jouant ce rôle. On peut alors y accèder en l'appelant par son nom, \verb#id# la plupart du temps, sauf s'il a été personnalisé, ou bien par l'attribut générique \verb#pk#, toujours présent pour désigner la \verb#PRIMARY KEY# d'un modèle, quelle qu'elle soit. @@ -204,24 +239,111 @@ class Club(models.Model): # (1) \label{ssub:Les migrations} \par Les migrations sont à lancer à chaque fois que l'on modifie un modèle. Elles permettent de conserver la base de donnée tout en la faisant évoluer dans sa structure, pour ajouter ou supprimer une colonne dans une table par exemple. -\par Lancer la commande \verb#./manage.py makemigration [nom de l'appli]# va permettre de générer un fichier Python +\par Lancer la commande \verb#./manage.py makemigrations [nom de l'appli]# va permettre de générer un fichier \emph{Python} automatiquement, qui sera mis à la suite des précédents, et qui sera appliqué sur la base au moment du lancement de \verb#./manage.py migrate#. \subsection{Les vues} \label{sub:les_vues} +\par Les vues sont les parties de code s'occupant de l'interface avec l'utilisateur. Elles sont appelées par les URLs, +et renvoient des réponses HTTP en fonction du traitement effectué. \subsubsection{Les URL} \label{ssub:Les URL} +\par Les URLs sont définies par application, et centralisées dans le dossier du projet. Il s'agit à chaque fois d'une +liste d'appel à la fonction \verb#url()#, qui comprends toujours une expression rationnelle décrivant l'URL, une +fonction passée en tant que callback qui sera appelé au moment où l'URL est résolue, et enfin un nom, permettant de s'y +référer dans les fonctiones de résolution inverse, comme dans les templates par exemple. Nous détaillerons cette +utilisation plus tard. + +\par Pour garder une organisation claire, les URLs sont classées par espaces de noms (namespace) afin d'avoir à éviter +de préfixer tous les noms pour s'y retrouver. Le namespace d'une URL est généralement le même nom que celui de +l'application dans laquelle elle se trouve. \subsubsection{Les fonctions de vue} \label{ssub:Les fonctions de vue} +\par Une fonction de vue prend toujours en paramètre une variable \verb#request# et renvoie toujours un objet +\verb#HTTPResponse#, contenant un code de retour HTTP, ainsi qu'une chaîne de caractères contenant la réponse en elle +même. +\par Entre temps, le traitement des informations permet de mettre à jour, de créer, ou de supprimer les objets définis +dans les modèles, par le biais des paramètres passé dans la requête. Ainsi, on peut accèder aux informations des +variables \verb#GET# et \verb#POST# très facilement en appelant respectivement \verb#request.GET['ma_clef']# et +\verb#request.POST['ma_clef']#, ces deux variables fonctionnant comme des dictionnaires. \subsubsection{Des vues basées sur des classes} \label{ssub:Des vues basées sur des classes} +\par Les vues en \emph{Django} peuvent aussi être définies comme des classes. Elles héritent alors à ce moment là toutes de la +classe \verb#View#, mais ont toutefois souvent beaucoup d'intermédiaire et n'héritent donc pas directement de cette +dernière. +\par L'avantage de ces vues sous forme de classe est de pouvoir séparer toute la chaîne de traitement entre les +différentes méthodes, et ainsi permettre, en jouant avec l'héritage, de fournir alors très peu d'informations à la +classe, tout en lui permettant d'effectuer un travail correct. +\par Ainsi, on retrouve de base, dans les filles de \verb#View#, un grand nombre de classes prédéfinies pour la plupart +des comportement. \verb#DetailView#, \verb#CreateView#, \verb#ListView#, sont quelques exemples de classes affichant +respectivement un objet en détails, un formulaire pour créer un nouvel objet, et enfin une liste d'objets. Il existe +cependant un bon nombre de ces vues fournissant d'autres fonctionnalités, et si malgré tout, aucune ne peut convenir, il +reste possible de se baser sur l'une d'elle et surcharger l'une de ses fonctions pour l'adapter à ses besoins. +\par L'écosystème des \verb#class-based views# étant toutefois assez complexe et riche, un site web a été créé afin +d'offrir un bon résumé de la situation: \emph{Classy class-based views}, accessible à l'adresse +\url{http://ccbv.co.uk/}. \section{Jinja2} \label{sec:jinja2} +\par \emph{Jinja2} est un moteur de template écrit en \emph{Python} qui s'inspire fortement de la syntaxe des templates de +\emph{Django}, mais qui apporte toutefois sont lot d'améliorations non négligeable. En effet, l'ajout des macros, par +exemple, permet de factoriser une grande partie du code. +\par Un moteur de template permet de générer du contenu textuel de manière procédural en fonction des données à +afficher. Cela permet en pratique de pouvoir inclure du code proche de \emph{Python} dans la syntaxe au milieu d'un +document contenant principalement du HTML. Ainsi, si on a une liste d'objet, on peut facilement executer une boucle +\verb#for# afin de faire afficher simplement tous les objets selon le même format. +\noindent De même, il est facile d'inclure un \verb#if# pour décider à l'execution d'afficher ou non un lien en fonction +des droits que l'utilisateur possède sur le site. +\par En plus des structures conditionnelles classiques, un moteur de templates permet de formater des données plus +simplement, comme par exemple des dates, en fonction de la langue actuellement utilisée par l'utilisateur. +\par Enfin, bien utilisés, les templates permettent d'utiliser des fonctions d'inclusion, ce qui permet de hiérarchiser +les fichiers, et de s'assurer de l'unité de certaines parties du site. Ainsi, les \emph{headers}, les \emph{footers}, et +autres menus que l'on retrouve sur toutes les pages du site sont définis chacun dans un seul fichier et inclus dans +tous les autres. + +\subsection{Exemple de template Jinja2} +\label{sub:exemple_de_template_jinja2} + + +\begin{addmargin}[-7em]{0em} + \begin{minted}{jinja} +{% extends "core/base.jinja" %} + +{% block title %} + {{ user.get_display_name() }}'s tools +{% endblock %} + +{% block content %} +

User Tools

+

Back to profile

+ +

Sith management

+ +

Clubs

+ +{% endblock %} + \end{minted} +\end{addmargin} + % TODO: bases des templates Jinja2