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