doc/book/devrepo/entityclasses/data-as-objects.rst
author Christophe de Vienne <christophe@unlish.com>
Thu, 08 Jan 2015 22:11:06 +0100
changeset 10491 c67bcee93248
parent 10222 doc/book/en/devrepo/entityclasses/data-as-objects.rst@75d6096216d7
child 12556 d1c659d70368
permissions -rw-r--r--
[doc] Restructure the documentation * Create a new index file * Move the sphinx configuration files do the documentation root * Move book/README to dev/documenting.rst * Move book/mode_plan.py to tools/ * Move book/en/images to images * Move book/en/* to book/ * Move changelogs to changes/* * Adapt the Makefile * Add a title to the javascript api index Related to #4832808

Access to persistent data
--------------------------

Python-level access to persistent data is provided by the
:class:`Entity <cubicweb.entity>` class.

.. XXX this part is not clear. refactor it.

An entity class is bound to a schema entity type. Descriptors are added when
classes are registered in order to initialize the class according to its schema:

* the attributes defined in the schema appear as attributes of these classes

* the relations defined in the schema appear as attributes of these classes,
  but are lists of instances

`Formatting and output generation`:

* :meth:`view(__vid, __registry='views', **kwargs)`, applies the given view to the entity
  (and returns a unicode string)

* :meth:`absolute_url(*args, **kwargs)`, returns an absolute URL including the base-url

* :meth:`rest_path()`, returns a relative REST URL to get the entity

* :meth:`printable_value(attr, value=_marker, attrtype=None, format='text/html', displaytime=True)`,
  returns a string enabling the display of an attribute value in a given format
  (the value is automatically recovered if necessary)

`Data handling`:

* :meth:`as_rset()`, converts the entity into an equivalent result set simulating the
  request `Any X WHERE X eid _eid_`

* :meth:`complete(skip_bytes=True)`, executes a request that recovers at
  once all the missing attributes of an entity

* :meth:`get_value(name)`, returns the value associated to the attribute name given
  in parameter

* :meth:`related(rtype, role='subject', limit=None, entities=False)`,
  returns a list of entities related to the current entity by the
  relation given in parameter

* :meth:`unrelated(rtype, targettype, role='subject', limit=None)`,
  returns a result set corresponding to the entities not (yet)
  related to the current entity by the relation given in parameter
  and satisfying its constraints

* :meth:`cw_set(**kwargs)`, updates entity's attributes and/or relation with the
  corresponding values given named parameters. To set a relation where this
  entity is the object of the relation, use `reverse_<relation>` as argument
  name.  Values may be an entity, a list of entities, or None (meaning that all
  relations of the given type from or to this object should be deleted).

* :meth:`copy_relations(ceid)`, copies the relations of the entities having the eid
  given in the parameters on the current entity

* :meth:`cw_delete()` allows to delete the entity


The :class:`AnyEntity` class
----------------------------

To provide a specific behavior for each entity, we can define a class
inheriting from `cubicweb.entities.AnyEntity`. In general, we define this class
in `mycube.entities` module (or in a submodule if we want to split code among
multiple files) so that it will be available on both server and client side.

The class `AnyEntity` is a sub-class of Entity that add methods to it,
and helps specializing (by further subclassing) the handling of a
given entity type.

Most methods defined for `AnyEntity`, in addition to `Entity`, add
support for the `Dublin Core`_ metadata.

.. _`Dublin Core`: http://dublincore.org/

`Standard meta-data (Dublin Core)`:

* :meth:`dc_title()`, returns a unicode string corresponding to the
  meta-data `Title` (used by default is the first non-meta attribute
  of the entity schema)

* :meth:`dc_long_title()`, same as dc_title but can return a more
  detailed title

* :meth:`dc_description(format='text/plain')`, returns a unicode string
  corresponding to the meta-data `Description` (looks for a
  description attribute by default)

* :meth:`dc_authors()`, returns a unicode string corresponding to the meta-data
  `Authors` (owners by default)

* :meth:`dc_creator()`, returns a unicode string corresponding to the
  creator of the entity

* :meth:`dc_date(date_format=None)`, returns a unicode string corresponding to
  the meta-data `Date` (update date by default)

* :meth:`dc_type(form='')`, returns a string to display the entity type by
  specifying the preferred form (`plural` for a plural form)

* :meth:`dc_language()`, returns the language used by the entity

Inheritance
-----------

When describing a data model, entities can inherit from other entities as is
common in object-oriented programming.

You have the possibility to redefine whatever pleases you, as follow:

.. sourcecode:: python

    from cubes.OTHER_CUBE import entities

    class EntityExample(entities.EntityExample):

        def dc_long_title(self):
            return '%s (%s)' % (self.name, self.description)

The most specific entity definition will always the one used by the
ORM. For instance, the new EntityExample above in mycube replaces the
one in OTHER_CUBE. These types are stored in the `etype` section of
the `vregistry`.

Notice this is different than yams schema inheritance, which is an
experimental undocumented feature.


Application logic
-----------------

While a lot of custom behaviour and application logic can be
implemented using entity classes, the programmer must be aware that
adding new attributes and method on an entity class adds may shadow
schema-level attribute or relation definitions.

To keep entities clean (mostly data structures plus a few universal
methods such as listed above), one should use `adapters` (see
:ref:`adapters`).