[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.