goa/doc/devmanual_fr/sect_definition_entites.txt
author Julien Jehannet <Julien Jehannet <julien.jehannet@logilab.fr>>
Tue, 02 Mar 2010 21:48:36 +0100
branchstable
changeset 4783 6dc34d4cf892
parent 0 b97547f5f1fa
permissions -rw-r--r--
[F] views: fix 2 unicode errors 1. You can now use valid unicode strings in ValidationError exception. Previously, if 'err' contains unicode, UnicodeDecodeError was raised by format_errors() >>> templstr = '<li>%s</li>\n' >>> e = ValidationError(None, {None: u'oué, une exception en unicode!'}) >>> templstr % e '<li>None (None): ou\xc3\xa9, une exception en unicode!</li>\n' >>> templstr = u'<li>%s</li>\n' >>> templstr % e u'<li>None (None): ou\xe9, une exception en unicode!</li>\n' 2. The message of an Exception can contains unicode. But it now properly managed by “informal” string representation. We can easily fix the problem by using the Exception.message attribute that still contains the original message. >>> a = AssertionError(u'séfdsdf') >>> a.message u's\xe9fdsdf' >>> str(a) Traceback (most recent call last): File "<stdin>", line 1, in <module> UnicodeEncodeError: 'ascii' codec can't encode character u'\xe9' in position 1: ordinal not in range(128) >>> a = ValueError(u'fsdfsdéfsdfs') >>> str(a) Traceback (most recent call last): File "<stdin>", line 1, in <module> UnicodeEncodeError: 'ascii' codec can't encode character u'\xe9' in position 6: ordinal not in range(128) >>> a ValueError(u'fsdfsd\xe9fsdfs',) >>> unicode(a) Traceback (most recent call last): File "<stdin>", line 1, in <module> UnicodeEncodeError: 'ascii' codec can't encode character u'\xe9' in position 6: ordinal not in range(128) >>> a.message u'fsdfsd\xe9fsdfs'

Paramtrages et extensions spcifiques
--------------------------------------

Valeurs par dfaut dynamiques
`````````````````````````````
Il est possible de dfinir dans le schma des valeurs par dfaut *statiques*.
Il est galement possible de dfinir des valeurs par dfaut *dynamiques* en 
dfinissant sur la classe d'entit une mthode `default_<nom attribut>` pour
un attribut donne.


Contrle des attributs chargs et du tri par dfaut
```````````````````````````````````````````````````
* l'attribut de classe `fetch_attrs` permet de dfinir sur une classe d'entit
  la liste des noms des attributs ou relations devant tre chargs 
  automatiquement lors de la rcupration d'entit(s) de ce type. Dans le cas 
  des relations, on est limit aux relations *sujets de cardinalit `?` ou `1`*.

* la mthode de classe `fetch_order(attr, var)` prend en argument un nom 
  d'attribut (ou de relation) et un nom de variable et doit retourner une chaine
   utiliser dans la close "ORDERBY" d'une requte RQL pour trier 
  automatiquement les listes d'entits de ce type selon cet attribut, ou `None`
  si l'on ne veut pas de tri sur l'attribut pass en argument. Par dfaut les 
  entits sont tries selon leur date de cration

* la mthode de classe `fetch_unrelated_order(attr, var)` est similaire  la 
  mthode `fetch_order` mais est utilise essentiellement pour contrler le tri
  des listes droulantes permettant de crer des relations dans la vue d'dition
  d'une entit

La fonction `fetch_config(fetchattrs, mainattr=None)` permet de simplifier la 
dfinition des attributs  prcharger et du tri en retournant une liste des 
attributs  prcharger (en considrant ceux de la classe  `AnyEntity`
automatiquement) et une fonction de tri sur l'attribut "principal" (le 2eme 
argument si spcifi ou sinon le premier attribut de la liste `fetchattrs`).
Cette fonction est dfinie dans le package `cubicweb.entities`.

Par exemple : ::

  class Transition(AnyEntity):
    """..."""
    id = 'Transition'
    fetch_attrs, fetch_order = fetch_config(['name'])

Indique que pour le type d'entit "Transition" il faut prcharger l'attribut
"name" et trier par dfaut selon cet attribut.


Contrle des formulaires d'dition
``````````````````````````````````
Il est possible de contrler les attributs/relations dans la vue d'dition
simple ou multiple  l'aide des *rtags* suivants :

* `primary`, indique qu'un attribut ou une relation doit tre incorpor dans
  les formulaires d'dition simple et multiple. Dans le cas d'une relation,
  le formulaire d'dition de l'entit lie sera inclus dans le formulaire

* `secondary`, indique qu'un attribut ou une relation doit tre incorpor dans
  le formulaire d'dition simple uniquement. Dans le cas d'une relation,
  le formulaire d'dition de l'entit lie sera inclus dans le formulaire

* `generic`, indique qu'une relation doit tre incorpor dans le formulaire 
  d'dition simple dans la boite gnrique d'ajout de relation

* `generated`, indique qu'un attribut est cacul dynamiquement ou autre, et 
  qu'il ne doit donc pas tre prsent dans les formulaires d'dition

Au besoin il est possible de surcharger la mthode 
`relation_category(rtype, x='subject')` pour calculer dynamiquement la catgorie
d'dition d'une relation.


Contrle de la bote "add_related"
``````````````````````````````````
La boite `add related` est une boite automatique proposant de crer une entit
qui sera automatiquement lie  l'entit de dpart (le contexte dans lequel 
s'affiche la boite). Par dfaut, les liens prsents dans cette boite sont 
calculs en fonction des proprits du schma de l'entit visualise, mais il
est possible de les spcifier explicitement  l'aide des *rtags* suivants :

* `link`, indique qu'une relation est gnralement cre vers une entit
  existante et qu'il ne faut donc pas faire apparaitre de lien pour cette 
  relation

* `create`, indique qu'une relation est gnralement cre vers de nouvelles
  entits et qu'il faut donc faire apparaitre un lien pour crer une nouvelle
  entit et la lier automatiquement

Au besoin il est possible de surcharger la mthode  
`relation_mode(rtype, targettype, x='subject')` pour caculer dynamiquement la
catgorie de cration d'une relation.

A noter galement que si au moins une action dans la catgorie "addrelated" est
trouve pour le contexte courant, le fonctionnement automatique est dsactiv
en faveur du fonctionnement explicite (i.e. affichage des actions de la
catgorie "addrelated" uniquement).

Contrle des formulaires de filtrage de table
`````````````````````````````````````````````
La vue "table" par dfaut gre dynamiquement un formulaire de filtrage du
contenu de celle-ci. L'algorithme est le suivant : 

1. on considre que la premire colonne contient les entits  restreindre
2. on recupre la premire entit de la table (ligne 0) pour "reprsenter"
   toutes les autres
3. pour toutes les autres variables dfinies dans la requte originale :

   1. si la variable est lie  la variable principale par au moins une
      n'importe quelle relation
   2. on appelle la mthode `filterform_vocabulary(rtype, x)` sur l'entit
      et si rien est retourn (ou plus exactement un tuple de valeur `None`,
      voir ci-dessous) on passe  la variable suivante, sinon un lment de
      formulaire de filtrage sera cr avec les valeurs de vocabulaire
      retournes

4. il n'y a pas d'autres limitations sur le rql, il peut comporter des clauses
   de tris, de groupes... Des fonctions javascripts sont utilises pour
   regnrer une requte  partir de la requte de dpart et des valeurs
   slctionnes dans les filtres de formulaire.

   
La mthode `filterform_vocabulary(rtype, x, var, rqlst, args, cachekey)` prend
en argument le nom d'une relation et la "cible", qui indique si l'entit sur
laquelle la mthode est appelle est sujet ou objet de la relation. Elle doit
retourner :

* un 2-uple de None si elle ne sait pas grer cette relation

* un type et une liste contenant le vocabulaire

  * la liste doit contenir des couples (valeur, label)
  * le type indique si la valeur dsigne un nombre entier (`type == 'int'`), une
    chane de  caractres (`type == 'string'`) ou une entit non finale (`type
    == 'eid'`)

Par exemple dans notre application de gestion de tickets, on veut pouvoir
filtrs ceux-ci par : 

* type
* priorit
* tat (in_state)
* tiquette (tags)
* version (done_in)

On dfinit donc la mthode suivante : ::


    class Ticket(AnyEntity):

	...

	def filterform_vocabulary(self, rtype, x, var, rqlst, args, cachekey):
	    _ = self.req._
	    if rtype == 'type':
		return 'string', [(x, _(x)) for x in ('bug', 'story')]
	    if rtype == 'priority':
		return 'string', [(x, _(x)) for x in ('minor', 'normal', 'important')]
	    if rtype == 'done_in':
		rql = insert_attr_select_relation(rqlst, var, rtype, 'num')
		return 'eid', self.req.execute(rql, args, cachekey)
	    return super(Ticket, self).filterform_vocabulary(rtype, x, var, rqlst,
							     args, cachekey)

							     
NOTE: Le support du filtrage sur les tiquettes et l'tat est install
automatiquement, pas besoin de le grer ici.