goa/doc/devmanual_fr/chap_bases_framework_erudi.txt
changeset 0 b97547f5f1fa
child 1398 5fe84a5f7035
equal deleted inserted replaced
-1:000000000000 0:b97547f5f1fa
       
     1 Fondements du framework CubicWeb
       
     2 =============================
       
     3 
       
     4 Le moteur web d'cubicweb consiste en quelques classes gérant un ensemble d'objets
       
     5 chargés dynamiquement au lancement d'cubicweb. Ce sont ces objets dynamiques, issus
       
     6 du modèle ou de la librairie, qui construisent le site web final. Les différents
       
     7 composants dynamiques sont par exemple : 
       
     8 
       
     9 * coté client et serveur
       
    10 
       
    11  - les définitions d'entités, contenant la logique permettant la manipulation des
       
    12    données de l'application
       
    13 
       
    14 * coté client
       
    15 
       
    16   - les *vues* , ou encore plus spécifiquement 
       
    17 
       
    18     - les boites
       
    19     - l'en-tête et le pied de page
       
    20     - les formulaires
       
    21     - les gabarits de pages
       
    22 
       
    23   - les *actions*
       
    24   - les *controleurs*
       
    25 
       
    26 * coté serveur
       
    27 
       
    28   - les crochets de notification
       
    29   - les vues de notification
       
    30 
       
    31 Les différents composants du moteur sont :
       
    32 
       
    33 * un frontal web (seul twisted disponible pour le moment), transparent du point
       
    34   de vue des objets dynamiques
       
    35 * un objet encapsulant la configuration
       
    36 * un `vregistry` (`cubicweb.cwvreg`) contenant les objets chargés dynamiquements
       
    37 
       
    38 
       
    39 Détail de la procédure d'enregistrement
       
    40 ---------------------------------------
       
    41 Au démarage le `vregistry` ou base de registres inspecte un certain nombre de
       
    42 répertoires à la recherche de définition de classes "compatible". Après une
       
    43 procédure d'enregistrement les objets sont affectés dans différents registres
       
    44 afin d'être ensuite séléctionné dynamiquement pendant le fonctionnement de
       
    45 l'application.
       
    46 
       
    47 La classe de base de tout ces objets est la classe `AppRsetObject` (module
       
    48 `cubicweb.common.appobject`). 
       
    49 
       
    50 
       
    51 API Python/RQL
       
    52 --------------
       
    53 
       
    54 Inspiré de la db-api standard, avec un object Connection possédant les méthodes
       
    55 cursor, rollback et commit principalement. La méthode importante est la méthode
       
    56 `execute` du curseur :
       
    57 
       
    58 `execute(rqlstring, args=None, eid_key=None, build_descr=True)`
       
    59 
       
    60 :rqlstring: la requête rql à éxécuter (unicode)
       
    61 :args: si la requête contient des substitutions, un dictionnaire contenant les
       
    62        valeurs à utiliser
       
    63 :eid_key: 
       
    64    un détail d'implémentation du cache de requêtes RQL fait que si une substitution est
       
    65    utilisée pour introduire un eid *levant des ambiguités dans la résolution de
       
    66    type de la requête*, il faut spécifier par cet argument la clé correspondante
       
    67    dans le dictionnaire
       
    68 
       
    69 C'est l'objet Connection qui possède les méthodes classiques `commit` et
       
    70 `rollback`. Vous ne *devriez jamais avoir à les utiliser* lors du développement
       
    71 d'interface web sur la base du framework CubicWeb étant donné que la fin de la
       
    72 transaction est déterminée par celui-ci en fonction du succès d'éxécution de la
       
    73 requête. 
       
    74 
       
    75 NOTE : lors de l'éxécution de requêtes de modification (SET,INSERT,DELETE), si une
       
    76 requête génère une erreur liée à la sécurité, un rollback est systématiquement
       
    77 effectuée sur la transaction courante.
       
    78 
       
    79 
       
    80 La classe `Request` (`cubicweb.web`)
       
    81 ---------------------------------
       
    82 Une instance de requête est créée lorsque une requête HTTP est transmise au
       
    83 serveur web. Elle contient des informations telles que les paramètres de
       
    84 formulaires, l'utilisateur connecté, etc. 
       
    85 
       
    86 **De manière plus générale une requête représente une demande d'un utilisateur,
       
    87 que se soit par HTTP ou non (on parle également de requête rql coté serveur par
       
    88 exemple)**
       
    89 
       
    90 Une instance de la classe `Request` possède les attributs :
       
    91 
       
    92 * `user`, instance de`cubicweb.common.utils.User` correspondant à l'utilisateur
       
    93   connecté 
       
    94 * `form`, dictionaire contenant les valeurs de formulaire web
       
    95 * `encoding`, l'encodage de caractère à utiliser dans la réponse
       
    96 
       
    97 Mais encore :
       
    98 
       
    99 :Gestion des données de session:        
       
   100   * `session_data()`, retourne un dictionaire contenant l'intégralité des
       
   101     données de la session
       
   102   * `get_session_data(key, default=None)`, retourne la valeur associée à
       
   103     la clé ou la valeur `default` si la clé n'est pas définie
       
   104   * `set_session_data(key, value)`, associe une valeur à une clé
       
   105   * `del_session_data(key)`,  supprime la valeur associé à une clé
       
   106     
       
   107 
       
   108 :Gestion de cookie:
       
   109   * `get_cookie()`, retourne un dictionnaire contenant la valeur de l'entête
       
   110     HTTP 'Cookie'
       
   111   * `set_cookie(cookie, key, maxage=300)`, ajoute un en-tête HTTP `Set-Cookie`,
       
   112     avec une durée de vie 5 minutes par défault (`maxage` = None donne un cooke
       
   113     *de session"* expirant quand l'utilisateur ferme son navigateur
       
   114   * `remove_cookie(cookie, key)`, fait expirer une valeur
       
   115 
       
   116 :Gestion d'URL:
       
   117   * `url()`, retourne l'url complète de la requête HTTP
       
   118   * `base_url()`, retourne l'url de la racine de l'application
       
   119   * `relative_path()`, retourne chemin relatif de la requête
       
   120 
       
   121 :Et encore...:
       
   122   * `set_content_type(content_type, filename=None)`, place l'en-tête HTTP
       
   123     'Content-Type'
       
   124   * `get_header(header)`, retourne la valeur associé à un en-tête HTTP
       
   125     arbitraire de la requête
       
   126   * `set_header(header, value)`, ajoute un en-tête HTTP arbitraire dans la
       
   127     réponse 
       
   128   * `cursor()` retourne un curseur RQL sur la session
       
   129   * `execute(*args, **kwargs)`, raccourci vers .cursor().execute()
       
   130   * `property_value(key)`, gestion des propriétés (`EProperty`)
       
   131   * le dictionaire `data` pour stocker des données pour partager de
       
   132     l'information entre les composants *durant l'éxécution de la requête*.
       
   133 
       
   134 A noter que cette classe est en réalité abstraite et qu'une implémentation
       
   135 concrète sera fournie par le *frontend* web utilisé (en l'occurent *twisted*
       
   136 aujourd'hui). Enfin pour les vues ou autres qui sont éxécutés coté serveur,
       
   137 la majeure partie de l'interface de `Request` est définie sur la session
       
   138 associée au client. 
       
   139 
       
   140 
       
   141 La classe `AppObject`
       
   142 ---------------------
       
   143 
       
   144 En général :
       
   145 
       
   146 * on n'hérite pas directement des cette classe mais plutôt d'une classe
       
   147   plus spécifique comme par exemple `AnyEntity`, `EntityView`, `AnyRsetView`,
       
   148   `Action`...
       
   149 
       
   150 * pour être enregistrable, un classe fille doit définir son registre (attribut
       
   151   `__registry__`) et son identifiant (attribut `id`). Généralement on n'a pas à
       
   152   s'occuper du registre, uniquement de l'identifiant `id` :) 
       
   153 
       
   154 On trouve un certain nombre d'attributs et de méthodes définis dans cette classe
       
   155 et donc commune à tous les objets de l'application :
       
   156 
       
   157 A l'enregistrement, les attributs suivants sont ajoutés dynamiquement aux
       
   158 *classes* filles:
       
   159 
       
   160 * `vreg`, le `vregistry` de l'application
       
   161 * `schema`, le schéma de l'application
       
   162 * `config`, la configuration de l'application
       
   163 
       
   164 On trouve également sur les instances les attributs :
       
   165 
       
   166 * `req`, instance de `Request`
       
   167 * `rset`, le "result set" associé à l'objet le cas échéant
       
   168 * `cursor`, curseur rql sur la session
       
   169 
       
   170 
       
   171 :Gestion d'URL:
       
   172   * `build_url(method=None, **kwargs)`, retourne une URL absolue construites à
       
   173     partir des arguments donnés. Le *controleur* devant gérer la réponse
       
   174     peut-être spécifié via l'argument spécial `method` (le branchement est
       
   175     théoriquement bien effectué automatiquement :).
       
   176 
       
   177   * `datadir_url()`, retourne l'url du répertoire de données de l'application
       
   178     (contenant les fichiers statiques tels que les images, css, js...)
       
   179 
       
   180   * `base_url()`, raccourci sur `req.base_url()`
       
   181 
       
   182   * `url_quote(value)`, version *unicode safe* de de la fonction `urllib.quote`
       
   183 
       
   184 :Manipulation de données:
       
   185 
       
   186   * `etype_rset(etype, size=1)`, raccourci vers `vreg.etype_rset()`
       
   187 
       
   188   * `eid_rset(eid, rql=None, descr=True)`, retourne un objet result set pour
       
   189     l'eid donné
       
   190   * `entity(row, col=0)`, retourne l'entité correspondant à la position données
       
   191     du "result set" associé à l'objet
       
   192 
       
   193   * `complete_entity(row, col=0, skip_bytes=True)`, équivalent à `entity` mais
       
   194     appelle également la méthode `complete()` sur l'entité avant de la retourner
       
   195 
       
   196 :Formattage de données:
       
   197   * `format_date(date, date_format=None, time=False)`
       
   198   * `format_time(time)`,
       
   199 
       
   200 :Et encore...:
       
   201 
       
   202   * `external_resource(rid, default=_MARKER)`, accède à une valeur définie dans
       
   203     le fichier de configuration `external_resource`
       
   204     
       
   205   * `tal_render(template, variables)`, 
       
   206 
       
   207 
       
   208 **NOTE IMPORTANTE**
       
   209 Lorsqu'on hérite d'`AppObject` (même indirectement), il faut **toujours**
       
   210 utiliser **super()** pour récupérer les méthodes et attributs des classes
       
   211 parentes, et pas passer par l'identifiant de classe parente directement.
       
   212 (sous peine de tomber sur des bugs bizarres lors du rechargement automatique
       
   213 des vues). Par exemple, plutôt que d'écrire::
       
   214 
       
   215       class Truc(PrimaryView):
       
   216           def f(self, arg1):
       
   217               PrimaryView.f(self, arg1)
       
   218 
       
   219 Il faut écrire::
       
   220       
       
   221       class Truc(PrimaryView):
       
   222           def f(self, arg1):
       
   223               super(Truc, self).f(arg1)
       
   224 
       
   225 
       
   226 XXX FILLME diagramme interaction application/controller/template/view