goa/doc/devmanual_fr/chap_bases_framework_erudi.txt
author Sylvain Thénault <sylvain.thenault@logilab.fr>
Wed, 24 Feb 2010 10:56:47 +0100 (2010-02-24)
branchstable
changeset 4680 8a6bee838464
parent 1398 5fe84a5f7035
permissions -rw-r--r--
[test] update tests broken by changes on attributes permissions handling in yams (add/delete replaced by update
Fondements du framework CubicWeb
=============================

Le moteur web d'cubicweb consiste en quelques classes g�rant un ensemble d'objets
charg�s dynamiquement au lancement d'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)


XXX FILLME diagramme interaction application/controller/template/view