diff --git a/ideas/django-patterns.md b/ideas/django-patterns.md deleted file mode 100644 index acec614..0000000 --- a/ideas/django-patterns.md +++ /dev/null @@ -1,11 +0,0 @@ -# Django - -[Django](https://www.djangoproject.com/) est l'un des frameworks Web proposant une très bonne intégration des composants, et une flexibilité bien pensée: chacun des composants permet de définir son contenu de manière poussée, en respectant des contraintes logiques et faciles à retenir. - -En restant dans les sentiers battus, votre projet suivra le patron de conception `MVC` (Modèle-Vue-Controleur), avec une petite variante sur les termes utilisés: Django les nomme respectivement Modèle-Template-Vue: - - * Le modèle (`models.py`) fait le lien avec la base de données et permet de définir les champs et leur type à associer à une table. *Grosso modo*, une table SQL correspondra à une classe d'un modèle Django. - * La vue (`views.py`), qui joue le rôle de contrôleur: *a priori*, tous les traitements, la récupération des données, etc. doit passer par ce composant et ne doit (pratiquement) pas être généré à la volée, directement à l'affichage d'une page. - * Le template, qui s'occupe de la mise en forme: c'est le composant qui va s'occuper de transformer les données en un affichage compréhensible (avec l'aide du navigateur) pour l'utilisateur. - - diff --git a/make.bat b/make.bat index eb7a18f..34c806f 100644 --- a/make.bat +++ b/make.bat @@ -38,7 +38,7 @@ if "%1" == "html" ( ) if "%1" == "pdf" ( - asciidoctor-pdf -a pdf-themesdir=resources/themes -a pdf-theme=gwift-theme source/main.adoc -t + asciidoctor-pdf -a pdf-themesdir=resources/themes -a pdf-theme=basic source/main.adoc -t goto end ) diff --git a/resources/themes/basic-theme.yml b/resources/themes/basic-theme.yml new file mode 100644 index 0000000..7c737fd --- /dev/null +++ b/resources/themes/basic-theme.yml @@ -0,0 +1,14 @@ +extends: default +footer: + recto: + right: + content: '{section-or-chapter-title} | {page-number}' + verso: + left: + content: '{page-number} | {chapter-title}' +admonition: + icon: + caution: + name: fa-fire + stroke_color: ff0000 + size: 24 \ No newline at end of file diff --git a/source/images/diagrams/architecture.png b/source/images/diagrams/architecture.png new file mode 100644 index 0000000..cef440c Binary files /dev/null and b/source/images/diagrams/architecture.png differ diff --git a/source/images/diagrams/django-process.png b/source/images/diagrams/django-process.png new file mode 100644 index 0000000..6d6a20e Binary files /dev/null and b/source/images/diagrams/django-process.png differ diff --git a/source/part-1-workspace/django-lts-support.png b/source/images/django-support-lts.png similarity index 100% rename from source/part-1-workspace/django-lts-support.png rename to source/images/django-support-lts.png diff --git a/source/images/it-works-on-my-machine.jpg b/source/images/it-works-on-my-machine.jpg new file mode 100644 index 0000000..c9dd976 Binary files /dev/null and b/source/images/it-works-on-my-machine.jpg differ diff --git a/source/part-1-workspace/images/scenarii-de-plantages.png b/source/images/scenarii-de-plantages.png similarity index 100% rename from source/part-1-workspace/images/scenarii-de-plantages.png rename to source/images/scenarii-de-plantages.png diff --git a/source/part-1-workspace/00-main.adoc b/source/part-1-workspace/00-main.adoc index a4f141b..2d7c687 100644 --- a/source/part-1-workspace/00-main.adoc +++ b/source/part-1-workspace/00-main.adoc @@ -4,13 +4,13 @@ Avant de démarrer le développement, il est nécessaire de passer un peu de tem Les morceaux de code seront développés pour Python3.6+ et Django 3.0+. Ils nécessiteront peut-être quelques adaptations pour fonctionner sur une version antérieure. -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_). +Django fonctionne sur un https://docs.djangoproject.com/en/dev/internals/release-process/[roulement de trois versions mineures pour une version majeure], 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::images/django-support-lts.png[] 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. -Dans cette partie, on va parler de *méthode de travail*, avec un objectif visé. On peut éviter que l'application ne tourne que sur notre machine et que chaque déploiement ne soit une plaie à gérer. Chaque mise à jour doit se limiter au minimum: +Dans cette partie, on va parler de *méthode de travail*, avec un objectif visé. On peut éviter que l'application ne tourne que sur notre machine et que chaque déploiement ne soit une plaie à gérer. Chaque mise à jour doit se limiter à: . démarrer un script, . prévoir un rollback si cela plante diff --git a/source/part-1-workspace/environment.adoc b/source/part-1-workspace/environment.adoc index a307b63..ec2759a 100644 --- a/source/part-1-workspace/environment.adoc +++ b/source/part-1-workspace/environment.adoc @@ -1,8 +1,18 @@ -== Environnement de travail +== Boite à outils -Quelques idées: Git, VSCodium[https://vscodium.com/], un terminal (Si vous êtes sous Windows, cmder[https://cmder.net/]). +Un IDE : + +* https://vscodium.com/[VSCodium], avec les plugins https://marketplace.visualstudio.com/items?itemName=ms-python.python[Python], +* https://www.jetbrains.com/pycharm/[PyCharm] +* https://www.vim.org/[Vim] avec les plugins https://github.com/davidhalter/jedi-vim[Jedi-Vim], https://github.com/preservim/nerdtree[nerdtree] + +Un terminal : + +* Si vous êtes sous Windows, https://cmder.net/[cmder]. Un gestionnaire de base de données ? PHPMyAdmin ou PgAdmin. -Un IDE ? PyCharm, VSCodium, VIM, ... +Un gestionnaire de mots de passe : + +* https://keepassxc.org/[KeepassXC] (on en aura besoin ;-)) diff --git a/source/part-1-workspace/unit_tests.adoc b/source/part-1-workspace/unit_tests.adoc index 9c72c0a..da86ad0 100644 --- a/source/part-1-workspace/unit_tests.adoc +++ b/source/part-1-workspace/unit_tests.adoc @@ -2,9 +2,25 @@ Si on schématise l'infrastructure et le chemin parcouru par une éventuelle requête, on devrait arriver à quelque chose de synthéthique: -User -> Firefox -> http GET 1.1 -> Debian GNU/Linux -> Nginx -> gunicorn -> django -> url -> route -> fonction/classe/méthode -> construction -> accès à la base de données -> retour des données -> rendu -> réponse à l'utilisateur. +* Au niveau de l'infrastructure, + . l'utilisateur fait une requête via son navigateur (Firefox ou Chrome) + . le navigateur envoie une requête http, sa version, un verbe (GET, POST, ...), un port et éventuellement du contenu + . le firewall du serveur (Debian GNU/Linux, CentOS, ...) vérifie si la requête peut être prise en compte + . la requête est transmise à l'application qui écoute sur le port (probablement 80 ou 443; et _a priori_ Nginx) + . elle est ensuite transmise par socket et est prise en compte par Gunicorn + . qui la transmet ensuite à l'un de ses _workers_ (= un processus Python) + . après exécution, une réponse est renvoyée à l'utilisateur. -image::images/scenarii-de-plantages.png +image::images/diagrams/architecture.png[] + +* Au niveau logiciel (la partie mise en subrillance ci-dessus), la requête arrive dans les mains du processus Python, qui doit encore + . effectuer le routage des données, + . trouver la bonne fonction à exécuter, + . récupérer les données depuis la base de données, + . effectuer le rendu ou la conversion des données, + . et renvoyer une réponse à l'utilisateur. + +image::images/diagrams/django-process.png[] En gros, ça peut planter aux points suivants : @@ -14,7 +30,7 @@ En gros, ça peut planter aux points suivants : . Le verbe HTTP n'est pas pris en charge par la fonction . Le système n'a plus de place sur son disque . Nginx est mal configuré -. La communication par socket est mal configuré +. La communication par socket est mal configurée . L'URL est inconnue . La route n'existe pas . La base de dnnées est inaccessible diff --git a/source/part-1-workspace/venvs.adoc b/source/part-1-workspace/venvs.adoc index 27c5ed3..fcec70a 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::images/it-works-on-my-machine.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-2-deployment/00-main.adoc b/source/part-2-deployment/00-main.adoc index bff661e..9646a3e 100644 --- a/source/part-2-deployment/00-main.adoc +++ b/source/part-2-deployment/00-main.adoc @@ -1,8 +1,6 @@ = Déploiement -On va déjà parler de déploiement. Le serveur que django met à notre disposition est prévu uniquement pour le développement: inutile de passer par du code Python pour charger des fichiers statiques (feuilles de style, fichiers JavaScript, images, ...). De même, la base de donnée doit supporter plus qu'un seul utilisateur: SQLite fonctionne très bien dès lors qu'on se limite à un seul utilisateur... Sur une application Web, il est plus que probable que vous rencontriez rapidement des erreurs de base de données verrouillée pour écriture par un autre processus. Il est donc plus que bénéfique de passer sur quelque chose de plus solide. - -https://docs.djangoproject.com/fr/3.0/howto/deployment/[Déploiement]. +On va déjà parler de déploiement. Le serveur que django met à notre disposition est prévu uniquement pour le développement: inutile de passer par du code Python pour charger des fichiers statiques (feuilles de style, fichiers JavaScript, images, ...). De même, la base de donnée doit supporter plus qu'un seul utilisateur: SQLite fonctionne très bien dès lors qu'on se limite à un seul utilisateur... Sur une application Web, il est plus que probable que vous rencontriez rapidement des erreurs de base de données verrouillée pour écriture par un autre processus. Il est donc plus que bénéfique de passer sur quelque chose de plus solide. https://docs.djangoproject.com/fr/3.0/howto/deployment/[Déploiement]. Si vous avez suivi les étapes jusqu'ici, vous devriez à peine disposer d'un espace de travail proprement configuré, d'un modèle relativement basique et d'une configuration avec une base de données simpliste. En bref, vous avez quelque chose qui fonctionne, mais qui ressemble de très loin à ce que vous souhaitez au final. @@ -17,6 +15,28 @@ Dans cette partie, on abordera les points suivants: * Les différentes méthodes de supervision de l'application: comment analyser les fichiers de logs et comment intercepter correctement une erreur si elle se présente et comment remonter l'information. * Une partie sur la sécurité et la sécurisation de l'hôte. +Si on schématise l'infrastructure et le chemin parcouru par une éventuelle requête, on devrait arriver à quelque chose de synthéthique: + +* Au niveau de l'infrastructure, + . l'utilisateur fait une requête via son navigateur (Firefox ou Chrome) + . le navigateur envoie une requête http, sa version, un verbe (GET, POST, ...), un port et éventuellement du contenu + . le firewall du serveur (Debian GNU/Linux, CentOS, ...) vérifie si la requête peut être prise en compte + . la requête est transmise à l'application qui écoute sur le port (probablement 80 ou 443; et _a priori_ Nginx) + . elle est ensuite transmise par socket et est prise en compte par Gunicorn + . qui la transmet ensuite à l'un de ses _workers_ (= un processus Python) + . après exécution, une réponse est renvoyée à l'utilisateur. + +image::images/diagrams/architecture.png[] + +* Au niveau logiciel (la partie mise en subrillance ci-dessus), la requête arrive dans les mains du processus Python, qui doit encore + . effectuer le routage des données, + . trouver la bonne fonction à exécuter, + . récupérer les données depuis la base de données, + . effectuer le rendu ou la conversion des données, + . et renvoyer une réponse à l'utilisateur. + +image::images/diagrams/django-process.png[] + == Définition de l'infrastructure Comme on l'a vu dans la première partie, Django est un framework complet, intégrant tous les mécanismes nécessaires à la bonne évolution d'une application. On peut ainsi commencer petit, et suivre l'évolution des besoins en fonction de la charge estimée ou ressentie, ajouter un mécanisme de mise en cache, des logiciels de suivi, ... diff --git a/source/part-2-deployment/database.adoc b/source/part-2-deployment/database.adoc index 544d001..143aa1c 100644 --- a/source/part-2-deployment/database.adoc +++ b/source/part-2-deployment/database.adoc @@ -1,13 +1,14 @@ == Bases de données -On l'a déjà vu, Django se base sur un pattern type https://www.martinfowler.com/eaaCatalog/activeRecord.html[ActiveRecords] pour l'ORM et supporte les principaux moteurs de bases de données connus: +On l'a déjà vu, Django se base sur un pattern type https://www.martinfowler.com/eaaCatalog/activeRecord.html[ActiveRecords] pour la gestion de la persistance des données et supporte les principaux moteurs de bases de données connus: +* SQLite (en natif, mais Django 3.0 exige une version du moteur supérieure ou égale à la 3.8) * MariaDB (en natif depuis Django 3.0), * PostgreSQL au travers de psycopg2 (en natif aussi), * Microsoft SQLServer grâce aux drivers [...à compléter] -* ou Oracle via https://oracle.github.io/python-cx_Oracle/[cx_Oracle]. +* Oracle via https://oracle.github.io/python-cx_Oracle/[cx_Oracle]. -WARNING: Chaque pilote doit être utilisé précautionneusement ! Chaque version de Django n'est pas toujours compatible avec chacune des versions des pilotes, et chaque moteur de base de données nécessite parfois une version spécifique du pilote. Par ce fait, vous serez parfois bloqué sur une version de Django, simplement parce que votre serveur de base de données se trouvera dans une version spécifique (eg. Django 2.3 à cause d'un Oracle 12.1). +CAUTION: Chaque pilote doit être utilisé précautionneusement ! Chaque version de Django n'est pas toujours compatible avec chacune des versions des pilotes, et chaque moteur de base de données nécessite parfois une version spécifique du pilote. Par ce fait, vous serez parfois bloqué sur une version de Django, simplement parce que votre serveur de base de données se trouvera dans une version spécifique (eg. Django 2.3 à cause d'un Oracle 12.1). Ci-dessous, quelques procédures d'installation pour mettre un serveur à disposition. Les deux plus simples seront MariaDB et PostgreSQL, qu'on couvrira ci-dessous. Oracle et Microsoft SQLServer se trouveront en annexes. diff --git a/source/part-3-django-concepts/00-main.adoc b/source/part-3-django-concepts/00-main.adoc index 6fd7ad0..b5d0ffb 100644 --- a/source/part-3-django-concepts/00-main.adoc +++ b/source/part-3-django-concepts/00-main.adoc @@ -1,9 +1,15 @@ = Django -Dans ce chapitre, on va parler de plusieurs concepts utiles au développement rapide d'une application. On parlera de modélisation, de migrations, d'administration auto-générée. +Dans ce chapitre, on va parler de plusieurs concepts utiles au développement rapide d'une application. On parlera de modélisation, de migrations, d'administration auto-générée. C'est un framework Web proposant une très bonne intégration des composants, et une flexibilité bien pensée: chacun des composants permet de définir son contenu de manière poussée, en respectant des contraintes logiques et faciles à retenir. + +En restant dans les sentiers battus, votre projet suivra le patron de conception `MVC` (Modèle-Vue-Controleur), avec une petite variante sur les termes utilisés: Django les nomme respectivement Modèle-Template-Vue: + Dans un *pattern* MVC classique, la traduction immédiate du **contrôleur** est une **vue**. Et comme on le verra par la suite, la **vue** est en fait le **template**. -Les vues agrègent donc les informations à partir d'un des composants et les font transiter vers un autre. En d'autres mots, la vue sert de pont entre les données gérées par la base et l'interface utilisateur. + +* Le modèle (`models.py`) fait le lien avec la base de données et permet de définir les champs et leur type à associer à une table. _Grosso modo_*, une table SQL correspondra à une classe d'un modèle Django. +* La vue (`views.py`), qui joue le rôle de contrôleur: _a priori_, tous les traitements, la récupération des données, etc. doit passer par ce composant et ne doit (pratiquement) pas être généré à la volée, directement à l'affichage d'une page. En d'autres mots, la vue sert de pont entre les données gérées par la base et l'interface utilisateur. +* Le template, qui s'occupe de la mise en forme: c'est le composant qui va s'occuper de transformer les données en un affichage compréhensible (avec l'aide du navigateur) pour l'utilisateur. Pour reprendre une partie du schéma précédent, on a une requête qui est émise par un utilisateur. La première étape consiste à trouver une route qui correspond à cette requête, c'est à dire à trouver la correspondance entre l'URL demandée et la fonction qui sera exécutée. Cette fonction correspond au *contrôleur* et s'occupera de construire le *modèle* correspondant. diff --git a/source/part-3-django-concepts/auth.adoc b/source/part-3-django-concepts/auth.adoc index 9bd1ca7..c1c7f80 100644 --- a/source/part-3-django-concepts/auth.adoc +++ b/source/part-3-django-concepts/auth.adoc @@ -1,12 +1,8 @@ -================ -Authentification -================ +== Authentification -Comme on l'a vu dans la partie sur le modèle, nous souhaitons que le créateur d'une liste puisse retrouver facilement les éléments qu'il aura créé. Ce dont nous n'avons pas parlé cependant, c'est la manière dont l'utilisateur va pouvoir créer son compte et s'authentifier. La `document `_ est très complète, nous allons essayer de la simplifier au maximum. Accrochez-vous, le sujet peut être complexe. +Comme on l'a vu dans la partie sur le modèle, nous souhaitons que le créateur d'une liste puisse retrouver facilement les éléments qu'il aura créé. Ce dont nous n'avons pas parlé cependant, c'est la manière dont l'utilisateur va pouvoir créer son compte et s'authentifier. La https://docs.djangoproject.com/en/stable/topics/auth/[documentation] est très complète, nous allons essayer de la simplifier au maximum. Accrochez-vous, le sujet peut être complexe. -**************************** -Mécanisme d'authentification -**************************** +=== Mécanisme d'authentification On peut schématiser le flux d'authentification de la manière suivante : @@ -23,9 +19,9 @@ En résumé (bis): . Une personne souhaite se connecter; . Les backends d'authentification s'enchaîne jusqu'à trouver une bonne correspondance. Si aucune correspondance n'est trouvée, on envoie la personne sur les roses. -. Si OK, on retourne une instance de type curren_user, qui pourra être utilisée de manière uniforme dans l'application. +. Si OK, on retourne une instance de type current_user, qui pourra être utilisée de manière uniforme dans l'application. -Deux exemples : +Ci-dessous, on définit deux backends différents pour mieux comprendre les différentes possibilités: . Une authentification par jeton . Une authentification LDAP @@ -64,9 +60,7 @@ class TokenBackend(backends.ModelBackend): return None ---- - <1> Sous-entend qu'on a bien une classe qui permet d'accéder à ces jetons ;-) - - +<1> Sous-entend qu'on a bien une classe qui permet d'accéder à ces jetons ;-) [source,python] ---- @@ -102,76 +96,63 @@ class LdapBackend(backends.ModelBackend): On peut résumer le mécanisme d'authentification de la manière suivante: - * Si vous voulez modifier les informations liées à un utilisateur, orientez-vous vers la modification du modèle. Comme nous le verrons ci-dessous, il existe trois manières de prendre ces modifications en compte. Voir également `ici `_. + * Si vous voulez modifier les informations liées à un utilisateur, orientez-vous vers la modification du modèle. Comme nous le verrons ci-dessous, il existe trois manières de prendre ces modifications en compte. Voir également https://docs.djangoproject.com/en/stable/topics/auth/customizing/[ici]. * Si vous souhaitez modifier la manière dont l'utilisateur se connecte, alors vous devrez modifier le *backend*. -Modification du modèle -====================== +=== Modification du modèle -Dans un premier temps, Django a besoin de manipuler `des instances de type `_ ``django.contrib.auth.User``. Cette classe implémente les champs suivants: +Dans un premier temps, Django a besoin de manipuler https://docs.djangoproject.com/en/1.9/ref/contrib/auth/#user-model[des instances de type `django.contrib.auth.User`]. Cette classe implémente les champs suivants: - * ``username`` - * ``first_name`` - * ``last_name`` - * ``email`` - * ``password`` - * ``date_joined``. + * `username` + * `first_name` + * `last_name` + * `email` + * `password` + * `date_joined`. D'autres champs, comme les groupes auxquels l'utilisateur est associé, ses permissions, savoir s'il est un super-utilisateur, ... sont moins pertinents pour le moment. Avec les quelques champs déjà définis ci-dessus, nous avons de quoi identifier correctement nos utilisateurs. Inutile d'implémenter nos propres classes, puisqu'elles existent déjà :-) Si vous souhaitez ajouter un champ, il existe trois manières de faire. -Extension du modèle existant ----------------------------- +=== Extension du modèle existant -Le plus simple consiste à créer une nouvelle classe, et à faire un lien de type ``OneToOne`` vers la classe ``django.contrib.auth.User``. De cette manière, on ne modifie rien à la manière dont Django authentife ses utlisateurs: tout ce qu'on fait, c'est un lien vers une table nouvellement créée, comme on l'a déjà vu au point [...voir l'héritage de modèle]. L'avantage de cette méthode, c'est qu'elle est extrêmement flexible, et qu'on garde les mécanismes Django standard. Le désavantage, c'est que pour avoir toutes les informations de notre utilisateur, on sera obligé d'effectuer une jointure sur le base de données, ce qui pourrait avoir des conséquences sur les performances. +Le plus simple consiste à créer une nouvelle classe, et à faire un lien de type `OneToOne` vers la classe `django.contrib.auth.User`. De cette manière, on ne modifie rien à la manière dont Django authentife ses utlisateurs: tout ce qu'on fait, c'est un lien vers une table nouvellement créée, comme on l'a déjà vu au point [...voir l'héritage de modèle]. L'avantage de cette méthode, c'est qu'elle est extrêmement flexible, et qu'on garde les mécanismes Django standard. Le désavantage, c'est que pour avoir toutes les informations de notre utilisateur, on sera obligé d'effectuer une jointure sur le base de données, ce qui pourrait avoir des conséquences sur les performances. -Substitution ------------- +=== Substitution -Avant de commencer, sachez que cette étape doit être effectuée **avant la première migration**. Le plus simple sera de définir une nouvelle classe héritant de ``django.contrib.auth.User`` et de spécifier la classe à utiliser dans votre fichier de paramètres. Si ce paramètre est modifié après que la première migration ait été effectuée, il ne sera pas pris en compte. Tenez-en compte au moment de modéliser votre application. +Avant de commencer, sachez que cette étape doit être effectuée **avant la première migration**. Le plus simple sera de définir une nouvelle classe héritant de `django.contrib.auth.User` et de spécifier la classe à utiliser dans votre fichier de paramètres. Si ce paramètre est modifié après que la première migration ait été effectuée, il ne sera pas pris en compte. Tenez-en compte au moment de modéliser votre application. -.. code-block:: python +[source,python] +---- +AUTH_USER_MODEL = 'myapp.MyUser' +---- - AUTH_USER_MODEL = 'myapp.MyUser' +Notez bien qu'il ne faut pas spécifier le package `.models` dans cette injection de dépendances: le schéma à indiquer est bien `.`. -Notez bien qu'**il ne faut pas** spécifier le package ``.models`` dans cette injection de dépendances: le schéma à indiquer est bien ``.``. - -Backend -======= +==== Backend - - -********* -Templates -********* +==== Templates Ce qui n'existe pas par contre, ce sont les vues. Django propose donc tout le mécanisme de gestion des utilisateurs, excepté le visuel (hors administration). En premier lieu, ces paramètres sont fixés dans le fichier `settings `_. On y trouve par exemple les paramètres suivants: - * ``LOGIN_REDIRECT_URL``: si vous ne spécifiez pas le paramètre ``next``, l'utilisateur sera automatiquement redirigé vers cette page. - * ``LOGIN_URL``: l'URL de connexion à utiliser. Par défaut, l'utilisateur doit se rendre sur la page ``/accounts/login``. + * `LOGIN_REDIRECT_URL`: si vous ne spécifiez pas le paramètre `next`, l'utilisateur sera automatiquement redirigé vers cette page. + * `LOGIN_URL`: l'URL de connexion à utiliser. Par défaut, l'utilisateur doit se rendre sur la page `/accounts/login`. -*********************** -Social-Authentification -*********************** +==== Social-Authentification -Voir ici : `python social auth `_ +Voir ici : https://github.com/omab/python-social-auth[python social auth] -Un petit mot sur OAuth ----------------------- - -OAuth -===== +==== Un petit mot sur OAuth OAuth est un standard libre définissant un ensemble de méthodes à implémenter pour l'accès (l'autorisation) à une API. Son fonctionnement se base sur un système de jetons (Tokens), attribués par le possesseur de la ressource à laquelle un utilisateur souhaite accéder. Le client initie la connexion en demandant un jeton au serveur. Ce jeton est ensuite utilisée tout au long de la connexion, pour accéder aux différentes ressources offertes par ce serveur. `wikipedia `_. -Une introduction à OAuth est `disponible ici `_. Elle introduit le protocole comme étant une `valet key`, une clé que l'on donne à la personne qui va garer votre voiture pendant que vous profitez des mondanités. Cette clé donne un accès à votre voiture, tout en bloquant un ensemble de fonctionnalités. Le principe du protocole est semblable en ce sens: vous vous réservez un accès total à une API, tandis que le système de jetons permet d'identifier une personne, tout en lui donnant un accès restreint à votre application. +Une introduction à OAuth est http://hueniverse.com/oauth/guide/intro/[disponible ici]. Elle introduit le protocole comme étant une `valet key`, une clé que l'on donne à la personne qui va garer votre voiture pendant que vous profitez des mondanités. Cette clé donne un accès à votre voiture, tout en bloquant un ensemble de fonctionnalités. Le principe du protocole est semblable en ce sens: vous vous réservez un accès total à une API, tandis que le système de jetons permet d'identifier une personne, tout en lui donnant un accès restreint à votre application. L'utilisation de jetons permet notamment de définir une durée d'utilisation et une portée d'utilisation. L'utilisateur d'un service A peut par exemple autoriser un service B à accéder à des ressources qu'il possède, sans pour autant révéler son nom d'utilisateur ou son mot de passe. -L'exemple repris au niveau du `workflow `_ est le suivant : un utilisateur(trice), Jane, a uploadé des photos sur le site faji.com (A). Elle souhaite les imprimer au travers du site beppa.com (B). +L'exemple repris au niveau du http://hueniverse.com/oauth/guide/workflow/[workflow] est le suivant : un utilisateur(trice), Jane, a uploadé des photos sur le site faji.com (A). Elle souhaite les imprimer au travers du site beppa.com (B). Au moment de la commande, le site beppa.com envoie une demande au site faji.com pour accéder aux ressources partagées par Jane. Pour cela, une nouvelle page s'ouvre pour l'utilisateur, et lui demande d'introduire sa "pièce d'identité". Le site A, ayant reçu une demande de B, mais certifiée par l'utilisateur, ouvre alors les ressources et lui permet d'y accéder. diff --git a/source/part-9-bonus/00-main.adoc b/source/part-9-bonus/00-main.adoc new file mode 100644 index 0000000..d645a2f --- /dev/null +++ b/source/part-9-bonus/00-main.adoc @@ -0,0 +1,5 @@ += En Bonus + +include::code-snippets.adoc[] + +include::legacy.adoc[] diff --git a/source/bonus/code-snippets.adoc b/source/part-9-bonus/code-snippets.adoc similarity index 100% rename from source/bonus/code-snippets.adoc rename to source/part-9-bonus/code-snippets.adoc diff --git a/ideas/legacy.md b/source/part-9-bonus/legacy.adoc similarity index 90% rename from ideas/legacy.md rename to source/part-9-bonus/legacy.adoc index 69cc5ce..b0e2798 100644 --- a/ideas/legacy.md +++ b/source/part-9-bonus/legacy.adoc @@ -1,3 +1,5 @@ +== Applications _Legacy_ + Quand on intègre une nouvelle application Django dans un environement existant, la première étape est de se câbler sur la base de données existantes; 1. Soit l'application sur laquelle on se greffe restera telle quelle; @@ -6,4 +8,4 @@ Quand on intègre une nouvelle application Django dans un environement existant, Dans le premier cas, il convient de créer une application et de spécifier pour chaque classe l'attribute `managed = False` dans le `class Meta:` de la définition. Dans le second, il va falloir câbler deux-trois éléments avant d'avoir une intégration complète (comprendre: avec une interface d'admin, les migrations, les tests unitaires et tout le brol :)) - `python manage.py inspectdb > models.py` + `python manage.py inspectdb > models.py` \ No newline at end of file diff --git a/source/resources/themes/gwift-theme.yaml b/source/resources/themes/gwift-theme.yaml deleted file mode 100644 index f66a3bb..0000000 --- a/source/resources/themes/gwift-theme.yaml +++ /dev/null @@ -1,8 +0,0 @@ -extends: default -footer: - recto: - right: - content: '{section-or-chapter-title} | {page-number}' - verso: - left: - content: '{page-number} | {chapter-title}' \ No newline at end of file