From fec56cfb3de598dd82a5fed887524ab10314d68b Mon Sep 17 00:00:00 2001 From: Fred Date: Sun, 12 Apr 2020 20:36:46 +0200 Subject: [PATCH] fetch old django content --- source/images/xkcd-327.png | Bin 0 -> 31908 bytes source/part-1-workspace/00-main.adoc | 2 +- source/part-1-workspace/unit_tests.adoc | 4 +++ source/part-1-workspace/venvs.adoc | 2 +- source/part-3-django-concepts/00-main.adoc | 6 +++- .../auth.adoc | 0 .../forms.adoc | 34 +++++++++++------- .../logging.adoc | 0 .../mvc.adoc | 0 .../mvc/layout.adoc | 0 .../mvc/my-first-wishlists.png | Bin .../mvc/sessions.adoc | 0 .../mvc/templates.adoc | 0 .../mvc/urls.adoc | 0 .../mvc/views.adoc | 0 .../template-tag.adoc | 0 source/part-3-django-concepts/urls.adoc | 1 + 17 files changed, 34 insertions(+), 15 deletions(-) create mode 100644 source/images/xkcd-327.png rename source/{django => part-3-django-concepts}/auth.adoc (100%) rename source/{django => part-3-django-concepts}/forms.adoc (80%) rename source/{django => part-3-django-concepts}/logging.adoc (100%) rename source/{django => part-3-django-concepts}/mvc.adoc (100%) rename source/{django => part-3-django-concepts}/mvc/layout.adoc (100%) rename source/{django => part-3-django-concepts}/mvc/my-first-wishlists.png (100%) rename source/{django => part-3-django-concepts}/mvc/sessions.adoc (100%) rename source/{django => part-3-django-concepts}/mvc/templates.adoc (100%) rename source/{django => part-3-django-concepts}/mvc/urls.adoc (100%) rename source/{django => part-3-django-concepts}/mvc/views.adoc (100%) rename source/{django => part-3-django-concepts}/template-tag.adoc (100%) create mode 100644 source/part-3-django-concepts/urls.adoc diff --git a/source/images/xkcd-327.png b/source/images/xkcd-327.png new file mode 100644 index 0000000000000000000000000000000000000000..530ddc0473ec44d032181c4b8b13a93caa738c6d GIT binary patch literal 31908 zcmV)ZK&!urP)004R=004l4008;_004mL004C`008P>0026e000+nl3&F}00009 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 literal 0 HcmV?d00001 diff --git a/source/part-1-workspace/00-main.adoc b/source/part-1-workspace/00-main.adoc index dc43bf0..a4f141b 100644 --- a/source/part-1-workspace/00-main.adoc +++ b/source/part-1-workspace/00-main.adoc @@ -6,7 +6,7 @@ Les morceaux de code seront développés pour Python3.6+ et Django 3.0+. Ils né Django fonctionne sur un link:++roulement de trois versions mineures pour une version majeure++[https://docs.djangoproject.com/en/dev/internals/release-process/], clôturé par une version LTS (_Long Term Support_). -image::http://ser-libre.com.ar/wp-content/uploads/2016/11/django.png[Support des versions Django] +image:http://ser-libre.com.ar/wp-content/uploads/2016/11/django.png[Support des versions Django] Ce sera une bonne indication à prendre en considération pour nos dépendances, puisqu'en visant une version particulière, on ne devra pratiquement pas se soucier (bon, un peu quand même...) des dépendances à installer, pour peu qu'on reste sous un certain seuil. diff --git a/source/part-1-workspace/unit_tests.adoc b/source/part-1-workspace/unit_tests.adoc index dd25e18..9c72c0a 100644 --- a/source/part-1-workspace/unit_tests.adoc +++ b/source/part-1-workspace/unit_tests.adoc @@ -53,6 +53,10 @@ Vous trouverez ci-dessous une comparaison entre des tests avec les deux framewor ---- +=== Fixtures + +https://realpython.com/django-pytest-fixtures/[Lien]: super bien expliqué, et pourquoi les fixtures dans Pytest c'est 'achement plus mieux que les tests unitaires de Django. + === Couverture de code Dans un premier temps, *le pourcentage de code couvert par nos tests*. Une fois ce pourcentage évalué, le but du jeu va consister à *ce que ce pourcentage reste stable ou augmente*. Si vous modifiez une ligne de code et que la couverture passe de 73% à 72%, vous avez perdu et vous devez faire en sorte de corriger. diff --git a/source/part-1-workspace/venvs.adoc b/source/part-1-workspace/venvs.adoc index 7e333b2..27c5ed3 100644 --- a/source/part-1-workspace/venvs.adoc +++ b/source/part-1-workspace/venvs.adoc @@ -9,7 +9,7 @@ Cette pratique est cependant fortement déconseillée pour plusieurs raisons: . Il est tout à fait envisagable que deux applications différentes soient déployées sur un même hôte, et nécessitent chacune deux versions différentes d'une même dépendance. . Pour la reproductibilité d'un environnement spécifique. Cela évite notamment les réponses type "Ca juste marche chez moi", puisque la construction d'un nouvel environnement fait partie intégrante du processus de construction et de la documentation du projet; grace à elle, on a la possibilité de construire un environnement sain et d'appliquer des dépendances identiques, quelle que soit la machine hôte. -image::https://res.cloudinary.com/teepublic/image/private/s--hOdhXtVV--/t_Preview/b_rgb:ffffff,c_limit,f_jpg,h_630,q_90,w_630/v1464028809/production/designs/521845_1.jpg +image:https://res.cloudinary.com/teepublic/image/private/s--hOdhXtVV--/t_Preview/b_rgb:ffffff,c_limit,f_jpg,h_630,q_90,w_630/v1464028809/production/designs/521845_1.jpg Depuis la version 3.5 de Python, le module `venv` est https://docs.python.org/3/library/venv.html[recommandé] afin de créer un environnement virtuel. diff --git a/source/part-3-django-concepts/00-main.adoc b/source/part-3-django-concepts/00-main.adoc index a747f20..6680629 100644 --- a/source/part-3-django-concepts/00-main.adoc +++ b/source/part-3-django-concepts/00-main.adoc @@ -6,4 +6,8 @@ include::models.adoc[] include::admin.adoc[] -include::forms.adoc[] \ No newline at end of file +include::forms.adoc[] + +include::mvc.adoc[] + +include::urls.adoc[] \ No newline at end of file diff --git a/source/django/auth.adoc b/source/part-3-django-concepts/auth.adoc similarity index 100% rename from source/django/auth.adoc rename to source/part-3-django-concepts/auth.adoc diff --git a/source/django/forms.adoc b/source/part-3-django-concepts/forms.adoc similarity index 80% rename from source/django/forms.adoc rename to source/part-3-django-concepts/forms.adoc index c2bf7cd..6404d30 100644 --- a/source/django/forms.adoc +++ b/source/part-3-django-concepts/forms.adoc @@ -2,13 +2,13 @@ Ou comment valider proprement des données entrantes. -NOTE: intégrer le dessin XKCD avec Little Bobby Table sur l'assainissement des données en entrée :-p +image::images/xkcd-327.png[] Quand on parle de `forms`, on ne parle pas uniquement de formulaires Web. 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 `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 `.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. +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 https://docs.python.org/3/library/csv.html#csv.DictReader[DictReader]), et la version +++ à base de form. Les données fournies par un utilisateur **doivent** **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. @@ -19,13 +19,22 @@ Le flux à suivre est le suivant: . Traitement, si la validation a réussi. -Ils jouent également plusieurs rôles: +Ils jouent également deux rôles importants: -. Validation des données, en plus de celles déjà définies au niveau du modèle -. Contrôle sur le rendu à appliquer aux champs +. Valider des données, en plus de celles déjà définies au niveau du modèle +. Contrôler le rendu à appliquer aux champs. Ils agissent come une glue entre l'utilisateur et la modélisation de vos structures de données. +=== Flux de validation + +| .Validation +| .is_valid +| .clean_fields +↓ .clean_fields_machin + +NOTE: A compléter ;-) + === Dépendance avec le modèle Un **form** peut dépendre d'une autre classe Django. Pour cela, il suffit de fixer l'attribut `model` au niveau de la `class Meta` dans la définition. @@ -51,10 +60,13 @@ Le formulaire permet également de contrôler le rendu qui sera appliqué lors d [source,python] ---- -from django import forms from datetime import date + +from django import forms + from .models import Accident + class AccidentForm(forms.ModelForm): class Meta: model = Accident @@ -72,17 +84,18 @@ class AccidentForm(forms.ModelForm): 'class' : 'form-control', 'placeholder' : 'Context (why, where, ...)' }) + } ---- === 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. +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 `widget-tweaks`. === 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, ... Tout ça demande énormément de temps. Et c'est là qu'intervient `Django-Crispy-Forms `_. Cette librairie intègre plusieurs frameworks CSS (Bootstrap, Foundation et uni-form) et permet de contrôler entièrement le *layout* et la présentation. +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, ... Tout ça demande énormément de temps. Et c'est là qu'intervient 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 *layout* et la présentation. (c/c depuis le lien ci-dessous) @@ -96,11 +109,8 @@ Pour chaque champ, crispy-forms va : http://dotmobo.github.io/django-crispy-forms.html -== Validation des données -NOTE: parler ici des méthodes `clean`. - -== En conclusion +=== En conclusion . Toute donnée entrée par l'utilisateur **doit** passer par une instance de `form`. . euh ? diff --git a/source/django/logging.adoc b/source/part-3-django-concepts/logging.adoc similarity index 100% rename from source/django/logging.adoc rename to source/part-3-django-concepts/logging.adoc diff --git a/source/django/mvc.adoc b/source/part-3-django-concepts/mvc.adoc similarity index 100% rename from source/django/mvc.adoc rename to source/part-3-django-concepts/mvc.adoc diff --git a/source/django/mvc/layout.adoc b/source/part-3-django-concepts/mvc/layout.adoc similarity index 100% rename from source/django/mvc/layout.adoc rename to source/part-3-django-concepts/mvc/layout.adoc diff --git a/source/django/mvc/my-first-wishlists.png b/source/part-3-django-concepts/mvc/my-first-wishlists.png similarity index 100% rename from source/django/mvc/my-first-wishlists.png rename to source/part-3-django-concepts/mvc/my-first-wishlists.png diff --git a/source/django/mvc/sessions.adoc b/source/part-3-django-concepts/mvc/sessions.adoc similarity index 100% rename from source/django/mvc/sessions.adoc rename to source/part-3-django-concepts/mvc/sessions.adoc diff --git a/source/django/mvc/templates.adoc b/source/part-3-django-concepts/mvc/templates.adoc similarity index 100% rename from source/django/mvc/templates.adoc rename to source/part-3-django-concepts/mvc/templates.adoc diff --git a/source/django/mvc/urls.adoc b/source/part-3-django-concepts/mvc/urls.adoc similarity index 100% rename from source/django/mvc/urls.adoc rename to source/part-3-django-concepts/mvc/urls.adoc diff --git a/source/django/mvc/views.adoc b/source/part-3-django-concepts/mvc/views.adoc similarity index 100% rename from source/django/mvc/views.adoc rename to source/part-3-django-concepts/mvc/views.adoc diff --git a/source/django/template-tag.adoc b/source/part-3-django-concepts/template-tag.adoc similarity index 100% rename from source/django/template-tag.adoc rename to source/part-3-django-concepts/template-tag.adoc diff --git a/source/part-3-django-concepts/urls.adoc b/source/part-3-django-concepts/urls.adoc new file mode 100644 index 0000000..d868d4f --- /dev/null +++ b/source/part-3-django-concepts/urls.adoc @@ -0,0 +1 @@ +=== URLs \ No newline at end of file