doc/book/en/B0031-define-entities.en.txt
changeset 292 2d9e83c34b23
parent 229 767ff7f5d5a7
child 301 e47150482ac1
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/book/en/B0031-define-entities.en.txt	Tue Dec 23 13:50:56 2008 -0800
@@ -0,0 +1,168 @@
+.. -*- coding: utf-8 -*-
+
+Parametrization and specific extensions
+---------------------------------------
+
+Dynamic default values
+``````````````````````
+It is possible to define in the schema *static* default values.
+It is also possible to define in the schema *dynamic* default values
+by defining in the entity class a method `default_<attribut name>` for
+a given attribute.
+
+
+Loaded attributes and default sorting management
+````````````````````````````````````````````````
+
+* The class attribute `fetch_attrs` allows to defined in an entity class
+  a list of names of attributes or relations that should be automatically
+  loaded when we recover the entities of this type. In the case of relations,
+  we are limited to *subject of cardinality `?` or `1`* relations.
+
+* The class method `fetch_order(attr, var)` expects an attribute (or relation)
+  name as a parameter and a variable name, and it should return a string
+  to use in the requirement `ORDER BY` of an RQL query to automatically
+  sort the list of entities of such type according to this attribute, or
+  `None` if we do not want to sort on the attribute given in the parameter.
+  By default, the entities are sorted according to their creation date.
+
+* The class method `fetch_unrelated_order(attr, var)` is similar to the 
+  method `fetch_order` except that it is essentially used to control
+  the sorting of drop-down lists enabling relations creation in 
+  the editing view of an entity.
+
+The function `fetch_config(fetchattrs, mainattr=None)` simplifies the
+definition of the attributes to load and the sorting by returning a 
+list of attributes to pre-load (considering automatically the attributes
+of `AnyEntity`) and a sorting function based on the main attribute
+(the second parameter if specified otherwisethe first attribute from
+the list `fetchattrs`).
+This function is defined in `cubicweb.entities`.
+
+For example: ::
+
+  class Transition(AnyEntity):
+    """..."""
+    id = 'Transition'
+    fetch_attrs, fetch_order = fetch_config(['name'])
+
+Indicates that for the entity type "Transition", you have to pre-load
+the attribute `name` and sort by default on this attribute.
+
+
+Editing forms management
+````````````````````````
+It is possible to manage attributes/relations in the simple or multiple
+editing form thanks to the following *rtags*: 
+
+* `primary`, indicates that an attribute or a relation has to be inserted
+  in the simple or multiple editing forms. In the case of a relation,
+  the related entity editing form will be included in the editing form.
+
+* `secondary`, indicates that an attribute or a relation has to be inserted
+  in the simple editing form only. In the case of a relation, the related
+  entity editing form sill be included in the editing form.
+
+* `generic`, indicates that a relation has to be inserted in the simple
+  editing form, in the generic box of relation creation.
+
+* `generated`, indicates that an attribute is dynamically computed
+  or other,  and that it should not be displayed in the editing form.
+
+If necessarry, it is possible to overwrite the method  
+`relation_category(rtype, x='subject')` to dynamically compute
+a relation editing category.
+
+``add_related`` box management
+``````````````````````````````
+
+The box ``add_related`` is an automatic box that allows to create
+an entity automatically related to the initial entity (context in
+which the box is displayed). By default, the links generated in this
+box are computed from the schema properties of the displayed entity,
+but it is possible to explicitely specify them thanks to the
+following *rtags*:
+
+* `link`, indicates that a relation is in general created pointing
+  to an existing entity and that we should not to display a link
+  for this relation
+
+* `create`, indicates that a relation is in general created pointing
+  to new entities and that we should display a link to create a new
+  entity and link to it automatically
+
+
+If necessarry, it is possible to overwrite the method  
+`relation_mode(rtype, targettype, x='subject')` to dynamically
+compute a relation creation category.
+
+Please note that if at least one action belongs to the `addrelated` category,
+the automatic behavior is desactivated in favor of an explicit behavior
+(e.g. display of `addrelated` category actions only).
+
+
+Filtering table forms management
+````````````````````````````````
+
+By default, the view ``table`` manages automatically a filtering
+form of its content. The algorithm is as follows:
+
+1. we consider that the first column contains the entities to constraint
+2. we collect the first entity of the table (row 0) to represent all the 
+   others
+3. for all the others variables defined in the original request:
+   
+   1. if the varaible is related to the main variable by at least one relation
+   2. we call the method ``filterform_vocabulary(rtype, x)`` on the entity,
+      if nothing is returned (meaning a tuple `Non`, see below), we go to the
+      next variable, otherwise a form filtering element is created based on
+      the vocabulary values returned
+
+4. there is no others limitations to the `RQL`, it can include sorting, grouping
+   conditions... Javascripts functions are used to regenerate a request based on the
+   initial request and on the selected values from the filtering form.
+
+The method ``filterform_vocabulary(rtype, x, var, rqlst, args, cachekey)`` takes 
+the name of a relation and the target as parameters, which indicates of the
+entity on which we apply the method is subject or object of the relation. It
+has to return:
+
+* a 2-uple of None if it does not know how to handle the relation
+
+* a type and a list containing the vocabulary
+  
+  * the list has to contain couples (value, label)
+  * the type indicates if the value designate an integer (`type == 'int'`),
+    a string (`type =='string'` or a non-final relation (`type == 'eid'`)
+
+For example in our application managing tickets, we want to be able to filter
+them by :
+
+* type
+* priority
+* state (in_state)
+* tag (tags)
+* version (done_in)
+
+For that we define the following method: ::
+
+
+    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::
+  Filtering on state and tags is automatically installed, no need to handle it.
+