--- a/doc/book/fr/02-foundation.fr.txt Fri Dec 10 12:17:18 2010 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,431 +0,0 @@
-.. -*- coding: utf-8 -*-
-
-Fondements `CubicWeb`
-=====================
-Un peu d'histoire...
---------------------
-
-`CubicWeb` est une plate-forme logicielle de développement d'application web
-qui est développée par Logilab_ depuis 2001.
-
-
-Entièrement développée en Python, `CubicWeb` publie des données provenant
-de plusieurs sources telles que des bases de données SQL, des répertoire
-LDAP et des systèmes de gestion de versions tels que subversion.
-
-L'interface utilisateur de `CubicWeb` a été spécialement conçue pour laisser
-à l'utilisateur final toute latitude pour sélectionner puis présenter les données.
-Elle permet d'explorer aisément la base de connaissances et d'afficher les
-résultats avec la présentation la mieux adaptée à la tâche en cours.
-La flexibilité de cette interface redonne à l'utilisateur le contrôle de
-paramètres d'affichage et de présentation qui sont habituellement réservés
-aux développeurs.
-
-Parmi les applications déjà réalisées, on dénombre un annuaire en ligne pour
-le grand public (voir http://www.118000.fr/), un système de gestion d'études
-numériques et de simulations pour un bureau d'études, un service de garde
-partagée d'enfants (voir http://garde-partagee.atoukontact.fr/), la gestion
-du développement de projets logiciels (voir http://www.logilab.org), etc.
-
-En 2008, `CubicWeb` a été porté pour un nouveau type de source: le datastore
-de GoogleAppEngine_.
-
-.. _GoogleAppEngine: http://code.google.com/appengine/
-
-
-Architecture globale
---------------------
-.. image:: images/archi_globale.png
-
-**Note**: en pratique la partie cliente et la partie serveur sont
-généralement intégrées dans le même processus et communiquent donc
-directement, sans nécessiter des appels distants via Pyro. Il est
-cependant important de retenir que ces deux parties sont disjointes
-et qu'il est même possible d'en exécuter plusieurs exemplaires dans
-des processus distincts pour répartir la charge globale d'un site
-sur une ou plusieurs machines.
-
-Concepts et vocabulaire
------------------------
-
-*schéma*
- le schéma définit le modèle de données d'une application sous forme
- d'entités et de relations, grâce à la bibliothèque `yams`_. C'est
- l'élément central d'une application. Il est initialement défini sur
- le système de fichiers et est stocké dans la base de données lors de
- la création d'une instance. `CubicWeb` fournit un certain nombres de
- types d'entités inclus systématiquement car nécessaire au noyau
- `CubicWeb` et une librairie de cubes devant être inclus
- explicitement le cas échéant.
-
-*type d'entité*
- une entité est un ensemble d'attributs ; l'attribut de
- base de toute entité, qui est sa clef, est l'eid
-
-*type de relation*
- les entités sont liées entre elles par des relations. Dans `CubicWeb`
- les relations sont binaires : par convention on nomme le premier terme
- d'une relation son 'sujet' et le second son 'objet'.
-
-*type d'entité final*
- les types finaux correspondent aux types de bases comme les chaînes
- de caractères, les nombres entiers... Une propriété de ces types est
- qu'ils ne peuvent être utilisés qu'uniquement comme objet d'une
- relation. Les attributs d'une entité (non finale) sont des entités
- (finales).
-
-*type de relation finale*
- une relation est dite finale si son objet est un type final. Cela revient à
- un attribut d'une entité.
-
-*entrepôt*
- ou *repository*, c'est la partie serveur RQL de `CubicWeb`. Attention à ne pas
- confondre avec un entrepôt mercurial ou encore un entrepôt debian.
-
-*source*
- une source de données est un conteneur de données quelquonque (SGBD, annuaire
- LDAP...) intégré par l'entrepôt `CubicWeb`. Un entrepôt possède au moins une source
- dite "system" contenant le schéma de l'application, l'index plein-texte et
- d'autres informations vitales au système.
-
-*configuration*
- il est possible de créer différentes configurations pour une instance :
-
- - ``repository`` : entrepôt uniquement, accessible pour les clients via Pyro
- - ``twisted`` : interface web uniquement, communiquant avec un entrepôt via Pyro
- - ``all-in-one`` : interface web et entrepôt dans un seul processus. L'entrepôt
- peut ou non être accessible via Pyro
-
-*cube*
- un cube est un modèle regroupant un ou plusieurs types de données et/ou
- des vues afin de fournir une fonctionalité précise, ou une application `CubicWeb`
- complète utilisant éventuellement d'autres cube. Les différents
- cubes disponibles sur une machine sont installés dans
- `/path/to/forest/cubicweb/cubes`
-
-*instance*
- une instance est une installation spécifique d'un cube. Sont regroupes
- dans une instance tous les fichiers de configurations necessaires au bon
- fonctionnement de votre application web. Elle referrera au(x) cube(s) sur
- le(s)quel(s) votre application se base.
- Par exemple intranet/jpl et logilab.org sont deux instances du cube jpl que
- nous avons developpes en interne.
- Les instances sont définies dans le répertoire `~/etc/cubicweb.d`.
-
-*application*
- le mot application est utilisé parfois pour parler d'une instance et parfois
- d'un composant, en fonction du contexte... Mieux vaut donc éviter de
- l'utiliser et utiliser plutôt *cube* et *instance*.
-
-*result set*
- objet encaspulant les résultats d'une requête RQL et des informations sur
- cette requête.
-
-*Pyro*
- `Python Remote Object`_, système d'objets distribués pur Python similaire à
- Java's RMI (Remote Method Invocation), pouvant être utilisé pour la
- communication entre la partie web du framework et l'entrepôt RQL.
-
-.. _`Python Remote Object`: http://pyro.sourceforge.net/
-.. _`yams`: http://www.logilab.org/project/name/yams/
-
-
-Moteur `CubicWeb`
------------------
-
-Le moteur web de `CubicWeb` consiste en quelques classes gérant un ensemble d'objets
-chargés dynamiquement au lancement de `CubicWeb`. Ce sont ces objets dynamiques, issus
-du modèle ou de la librairie, qui construisent le site web final. Les différents
-composants dynamiques sont par exemple :
-
-* coté client et serveur
-
- - les définitions d'entités, contenant la logique permettant la manipulation des
- données de l'application
-
-* coté client
-
- - les *vues* , ou encore plus spécifiquement
-
- - les boites
- - l'en-tête et le pied de page
- - les formulaires
- - les gabarits de pages
-
- - les *actions*
- - les *controleurs*
-
-* coté serveur
-
- - les crochets de notification
- - les vues de notification
-
-Les différents composants du moteur sont :
-
-* un frontal web (seul twisted disponible pour le moment), transparent du point
- de vue des objets dynamiques
-* un objet encapsulant la configuration
-* un `vregistry` (`cubicweb.cwvreg`) contenant les objets chargés dynamiquements
-
-Détail de la procédure d'enregistrement
----------------------------------------
-Au démarage le `vregistry` ou base de registres inspecte un certain nombre de
-répertoires à la recherche de définition de classes "compatible". Après une
-procédure d'enregistrement les objets sont affectés dans différents registres
-afin d'être ensuite séléctionné dynamiquement pendant le fonctionnement de
-l'application.
-
-La classe de base de tout ces objets est la classe `AppRsetObject` (module
-`cubicweb.common.appobject`).
-
-
-API Python/RQL
---------------
-
-Inspiré de la db-api standard, avec un object Connection possédant les méthodes
-cursor, rollback et commit principalement. La méthode importante est la méthode
-`execute` du curseur :
-
-`execute(rqlstring, args=None, eid_key=None, build_descr=True)`
-
-:rqlstring: la requête rql à éxécuter (unicode)
-:args: si la requête contient des substitutions, un dictionnaire contenant les
- valeurs à utiliser
-:eid_key:
- un détail d'implémentation du cache de requêtes RQL fait que si une substitution est
- utilisée pour introduire un eid *levant des ambiguités dans la résolution de
- type de la requête*, il faut spécifier par cet argument la clé correspondante
- dans le dictionnaire
-
-C'est l'objet Connection qui possède les méthodes classiques `commit` et
-`rollback`. Vous ne *devriez jamais avoir à les utiliser* lors du développement
-d'interface web sur la base du framework `CubicWeb` étant donné que la fin de la
-transaction est déterminée par celui-ci en fonction du succès d'éxécution de la
-requête.
-
-NOTE : lors de l'éxécution de requêtes de modification (SET,INSERT,DELETE), si une
-requête génère une erreur liée à la sécurité, un rollback est systématiquement
-effectuée sur la transaction courante.
-
-
-La classe `Request` (`cubicweb.web`)
-------------------------------------
-Une instance de requête est créée lorsque une requête HTTP est transmise au
-serveur web. Elle contient des informations telles que les paramètres de
-formulaires, l'utilisateur connecté, etc.
-
-**De manière plus générale une requête représente une demande d'un utilisateur,
-que se soit par HTTP ou non (on parle également de requête rql coté serveur par
-exemple)**
-
-Une instance de la classe `Request` possède les attributs :
-
-* `user`, instance de`cubicweb.common.utils.User` correspondant à l'utilisateur
- connecté
-* `form`, dictionaire contenant les valeurs de formulaire web
-* `encoding`, l'encodage de caractère à utiliser dans la réponse
-
-Mais encore :
-
-:Gestion des données de session:
- * `session_data()`, retourne un dictionaire contenant l'intégralité des
- données de la session
- * `get_session_data(key, default=None)`, retourne la valeur associée à
- la clé ou la valeur `default` si la clé n'est pas définie
- * `set_session_data(key, value)`, associe une valeur à une clé
- * `del_session_data(key)`, supprime la valeur associé à une clé
-
-
-:Gestion de cookie:
- * `get_cookie()`, retourne un dictionnaire contenant la valeur de l'entête
- HTTP 'Cookie'
- * `set_cookie(cookie, key, maxage=300)`, ajoute un en-tête HTTP `Set-Cookie`,
- avec une durée de vie 5 minutes par défault (`maxage` = None donne un cooke
- *de session"* expirant quand l'utilisateur ferme son navigateur
- * `remove_cookie(cookie, key)`, fait expirer une valeur
-
-:Gestion d'URL:
- * `url()`, retourne l'url complète de la requête HTTP
- * `base_url()`, retourne l'url de la racine de l'application
- * `relative_path()`, retourne chemin relatif de la requête
-
-:Et encore...:
- * `set_content_type(content_type, filename=None)`, place l'en-tête HTTP
- 'Content-Type'
- * `get_header(header)`, retourne la valeur associé à un en-tête HTTP
- arbitraire de la requête
- * `set_header(header, value)`, ajoute un en-tête HTTP arbitraire dans la
- réponse
- * `cursor()` retourne un curseur RQL sur la session
- * `execute(*args, **kwargs)`, raccourci vers .cursor().execute()
- * `property_value(key)`, gestion des propriétés (`CWProperty`)
- * le dictionaire `data` pour stocker des données pour partager de
- l'information entre les composants *durant l'éxécution de la requête*.
-
-A noter que cette classe est en réalité abstraite et qu'une implémentation
-concrète sera fournie par le *frontend* web utilisé (en l'occurent *twisted*
-aujourd'hui). Enfin pour les vues ou autres qui sont éxécutés coté serveur,
-la majeure partie de l'interface de `Request` est définie sur la session
-associée au client.
-
-
-La classe `AppObject`
----------------------
-
-En général :
-
-* on n'hérite pas directement des cette classe mais plutôt d'une classe
- plus spécifique comme par exemple `AnyEntity`, `EntityView`, `AnyRsetView`,
- `Action`...
-
-* pour être enregistrable, un classe fille doit définir son registre (attribut
- `__registry__`) et son identifiant (attribut `id`). Généralement on n'a pas à
- s'occuper du registre, uniquement de l'identifiant `id` :)
-
-On trouve un certain nombre d'attributs et de méthodes définis dans cette classe
-et donc commune à tous les objets de l'application :
-
-A l'enregistrement, les attributs suivants sont ajoutés dynamiquement aux
-*classes* filles:
-
-* `vreg`, le `vregistry` de l'application
-* `schema`, le schéma de l'application
-* `config`, la configuration de l'application
-
-On trouve également sur les instances les attributs :
-
-* `req`, instance de `Request`
-* `rset`, le "result set" associé à l'objet le cas échéant
-* `cursor`, curseur rql sur la session
-
-
-:Gestion d'URL:
- * `build_url(method=None, **kwargs)`, retourne une URL absolue construites à
- partir des arguments donnés. Le *controleur* devant gérer la réponse
- peut-être spécifié via l'argument spécial `method` (le branchement est
- théoriquement bien effectué automatiquement :).
-
- * `datadir_url()`, retourne l'url du répertoire de données de l'application
- (contenant les fichiers statiques tels que les images, css, js...)
-
- * `base_url()`, raccourci sur `req.base_url()`
-
- * `url_quote(value)`, version *unicode safe* de de la fonction `urllib.quote`
-
-:Manipulation de données:
-
- * `etype_rset(etype, size=1)`, raccourci vers `vreg.etype_rset()`
-
- * `eid_rset(eid, rql=None, descr=True)`, retourne un objet result set pour
- l'eid donné
- * `entity(row, col=0)`, retourne l'entité correspondant à la position données
- du "result set" associé à l'objet
-
- * `complete_entity(row, col=0, skip_bytes=True)`, équivalent à `entity` mais
- appelle également la méthode `complete()` sur l'entité avant de la retourner
-
-:Formattage de données:
- * `format_date(date, date_format=None, time=False)`
- * `format_time(time)`,
-
-:Et encore...:
-
- * `external_resource(rid, default=_MARKER)`, accède à une valeur définie dans
- le fichier de configuration `external_resource`
-
- * `tal_render(template, variables)`,
-
-
-**NOTE IMPORTANTE**
-Lorsqu'on hérite d'`AppObject` (même indirectement), il faut **toujours**
-utiliser **super()** pour récupérer les méthodes et attributs des classes
-parentes, et pas passer par l'identifiant de classe parente directement.
-(sous peine de tomber sur des bugs bizarres lors du rechargement automatique
-des vues). Par exemple, plutôt que d'écrire::
-
- class Truc(PrimaryView):
- def f(self, arg1):
- PrimaryView.f(self, arg1)
-
-Il faut écrire::
-
- class Truc(PrimaryView):
- def f(self, arg1):
- super(Truc, self).f(arg1)
-
-
-
-
-
-
-Structure standard d'un cube
-----------------------------
-
-Un cube complexe est structuré selon le modèle suivant :
-
-::
-
- moncube/
- |
- |-- schema.py
- |
- |-- entities/
- |
- |-- sobjects/
- |
- |-- views/
- |
- |-- test/
- |
- |-- i18n/
- |
- |-- data/
- |
- |-- migration/
- | |- postcreate.py
- | \- depends.map
- |
- |-- debian/
- |
- \-- __pkginfo__.py
-
-On peut utiliser de simple module python plutôt que des répertoires (packages),
-par ex.:
-
-::
-
- moncube/
- |
- |-- entities.py
- |-- hooks.py
- \-- views.py
-
-
-où :
-
-* ``schema`` contient la définition du schéma (coté serveur uniquement)
-* ``entities`` contient les définitions d'entités (coté serveur et interface web)
-* ``sobjects`` contient les crochets et/ou vues de notification (coté serveur
- uniquement)
-* ``views`` contient les différents composants de l'interface web (coté interface
- web uniquement)
-* ``test`` contient les tests spécifiques à l'application (non installé)
-* ``i18n`` contient les catalogues de messages pour les langues supportées (coté
- serveur et interface web)
-* ``data`` contient des fichiers de données arbitraires servis statiquement
- (images, css, fichiers javascripts)... (coté interface web uniquement)
-* ``migration`` contient le fichier d'initialisation de nouvelles instances
- (``postcreate.py``) et générallement un fichier donnant les dépendances `CubicWeb` du
- composant en fonction de la version de celui-ci (``depends.map``)
-* ``debian`` contient les fichiers contrôlant le packaging debian (vous y
- trouverez les fichiers classiques ``control``, ``rules``, ``changelog``... (non
- installé)
-* le fichier ``__pkginfo__.py`` donne un certain nombre de méta-données sur le
- composant, notamment le nom de la distribution et la version courante (coté
- serveur et interface web) ou encore les sous-cubes utilisés par ce
- cube.
-
-Le strict minimum étant :
-
-* le fichier ``__pkginfo__.py``
-* la définition du schéma