structure architecture and software flow

This commit is contained in:
Fred Pauchet 2020-04-14 21:49:49 +02:00
parent 050b241646
commit 43ea71941a
20 changed files with 127 additions and 91 deletions

View File

@ -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.

View File

@ -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
)

View File

@ -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

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

View File

Before

Width:  |  Height:  |  Size: 40 KiB

After

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

View File

Before

Width:  |  Height:  |  Size: 898 KiB

After

Width:  |  Height:  |  Size: 898 KiB

View File

@ -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

View File

@ -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 ;-))

View File

@ -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

View File

@ -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.

View File

@ -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, ...

View File

@ -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.

View File

@ -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.

View File

@ -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 <https://docs.djangoproject.com/en/stable/topics/auth/>`_ 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 <https://docs.djangoproject.com/en/1.9/topics/auth/customizing/>`_.
* 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 <https://docs.djangoproject.com/en/1.9/ref/contrib/auth/#user-model>`_ ``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 `<nom de l'application>.<nom de la classe>`.
Notez bien qu'**il ne faut pas** spécifier le package ``.models`` dans cette injection de dépendances: le schéma à indiquer est bien ``<nom de l'application>.<nom de la classe>``.
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 <https://docs.djangoproject.com/en/1.8/ref/settings/#auth>`_. 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 <https://github.com/omab/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 <http://en.wikipedia.org/wiki/OAuth>`_.
Une introduction à OAuth est `disponible ici <http://hueniverse.com/oauth/guide/intro/>`_. 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 <http://hueniverse.com/oauth/guide/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.

View File

@ -0,0 +1,5 @@
= En Bonus
include::code-snippets.adoc[]
include::legacy.adoc[]

View File

@ -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`

View File

@ -1,8 +0,0 @@
extends: default
footer:
recto:
right:
content: '{section-or-chapter-title} | {page-number}'
verso:
left:
content: '{page-number} | {chapter-title}'