--- a/_exceptions.py Thu Apr 15 12:47:02 2010 +0200
+++ b/_exceptions.py Thu Apr 15 12:48:40 2010 +0200
@@ -122,8 +122,6 @@
class UnknownProperty(RegistryException):
"""property found in database but unknown in registry"""
-class RegistryOutOfDate(RegistryException):
- """raised when a source file modification is detected"""
# query exception #############################################################
--- a/cwconfig.py Thu Apr 15 12:47:02 2010 +0200
+++ b/cwconfig.py Thu Apr 15 12:48:40 2010 +0200
@@ -1,10 +1,8 @@
# -*- coding: utf-8 -*-
-#:organization: Logilab
-#:copyright: 2001-2010 LOGILAB S.A. (Paris, FRANCE), license is LGPL v2.
-#:contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr
-#:license: GNU Lesser General Public License, v2.1 - http://www.gnu.org/licenses
-
-# docstring included in doc/book/en/admin/setup.rst
+# organization: Logilab
+# copyright 2001-2010 LOGILAB S.A. (Paris, FRANCE), license is LGPL v2.
+# contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr
+# Licensed under the GNU Lesser General Public License, v2.1 - http://www.gnu.org/licenses
"""
.. _ResourceMode:
@@ -13,7 +11,7 @@
A resource *mode* is a predifined set of settings for various resources
directories, such as cubes, instances, etc. to ease development with the
-framework. There are two running modes with |cubicweb|:
+framework. There are two running modes with *CubicWeb*:
* 'user', resources are searched / created in the user home directory:
@@ -80,7 +78,7 @@
Python
``````
-If you installed |cubicweb| by cloning the Mercurial forest or from source
+If you installed *CubicWeb* by cloning the Mercurial forest or from source
distribution, then you will need to update the environment variable PYTHONPATH by
adding the path to the forest `cubicweb`:
@@ -89,7 +87,7 @@
export PYTHONPATH=/full/path/to/cubicweb-forest
-If you installed |cubicweb| with packages, no configuration is required and your
+If you installed *CubicWeb* with packages, no configuration is required and your
new cubes will be placed in `/usr/share/cubicweb/cubes` and your instances will
be placed in `/etc/cubicweb.d`.
@@ -97,11 +95,11 @@
CubicWeb
````````
-Here are all environment variables that may be used to configure |cubicweb|:
+Here are all environment variables that may be used to configure *CubicWeb*:
.. envvar:: CW_MODE
- Resource mode: user or system, as explained in :ref:ResourceMode.
+ Resource mode: user or system, as explained in :ref:`ResourceMode`.
.. envvar:: CW_CUBES_PATH
--- a/cwvreg.py Thu Apr 15 12:47:02 2010 +0200
+++ b/cwvreg.py Thu Apr 15 12:48:40 2010 +0200
@@ -185,7 +185,7 @@
from cubicweb import (ETYPE_NAME_MAP, Binary, UnknownProperty, UnknownEid,
ObjectNotFound, NoSelectableObject, RegistryNotFound,
- RegistryOutOfDate, CW_EVENT_MANAGER, onevent)
+ CW_EVENT_MANAGER, onevent)
from cubicweb.utils import dump_class
from cubicweb.vregistry import VRegistry, Registry, class_regid
from cubicweb.rtags import RTAGS
@@ -460,8 +460,8 @@
def itervalues(self):
return (value for key, value in self.items())
- def reset(self, path=None, force_reload=None):
- super(CubicWebVRegistry, self).reset(path, force_reload)
+ def reset(self):
+ super(CubicWebVRegistry, self).reset()
self._needs_iface = {}
# two special registries, propertydefs which care all the property
# definitions, and propertyvals which contains values for those
@@ -471,23 +471,12 @@
self['propertyvalues'] = self.eprop_values = {}
for key, propdef in self.config.eproperty_definitions():
self.register_property(key, **propdef)
- if path is not None and force_reload:
- cleanup_sys_modules(path)
- cubes = self.config.cubes()
- # if the fs code use some cubes not yet registered into the instance
- # we should cleanup sys.modules for those as well to avoid potential
- # bad class reference pb after reloading
- cfg = self.config
- for cube in cfg.expand_cubes(cubes, with_recommends=True):
- if not cube in cubes:
- cpath = cfg.build_vregistry_cube_path([cfg.cube_dir(cube)])
- cleanup_sys_modules(cpath)
def set_schema(self, schema):
"""set instance'schema and load application objects"""
self._set_schema(schema)
# now we can load application's web objects
- self._reload(self.config.vregistry_path(), force_reload=False)
+ self.reload(self.config.vregistry_path())
# map lowered entity type names to their actual name
self.case_insensitive_etypes = {}
for eschema in self.schema.entities():
@@ -496,12 +485,26 @@
clear_cache(eschema, 'ordered_relations')
clear_cache(eschema, 'meta_attributes')
- def _reload(self, path, force_reload):
+ def reload_if_needed(self):
+ path = self.config.vregistry_path()
+ if self.is_reload_needed(path):
+ self.reload(path)
+
+ def reload(self, path):
+ """modification detected, reset and reload the vreg"""
CW_EVENT_MANAGER.emit('before-registry-reload')
- # modification detected, reset and reload
- self.reset(path, force_reload)
- super(CubicWebVRegistry, self).register_objects(
- path, force_reload, self.config.extrapath)
+ cleanup_sys_modules(path)
+ cubes = self.config.cubes()
+ # if the fs code use some cubes not yet registered into the instance we
+ # should cleanup sys.modules for those as well to avoid potential bad
+ # class reference pb after reloading
+ cfg = self.config
+ for cube in cfg.expand_cubes(cubes, with_recommends=True):
+ if not cube in cubes:
+ cpath = cfg.build_vregistry_cube_path([cfg.cube_dir(cube)])
+ cleanup_sys_modules(cpath)
+ self.reset()
+ self.register_objects(path, True)
CW_EVENT_MANAGER.emit('after-registry-reload')
def _set_schema(self, schema):
@@ -546,15 +549,10 @@
if ifaces:
self._needs_iface[obj] = ifaces
- def register_objects(self, path, force_reload=None):
+ def register_objects(self, path, force_reload=False):
"""overriden to remove objects requiring a missing interface"""
- if force_reload is None:
- force_reload = self.config.debugmode
- try:
- super(CubicWebVRegistry, self).register_objects(
- path, force_reload, self.config.extrapath)
- except RegistryOutOfDate:
- self._reload(path, force_reload)
+ super(CubicWebVRegistry, self).register_objects(
+ path, force_reload, self.config.extrapath)
def initialization_completed(self):
"""cw specific code once vreg initialization is completed:
--- a/devtools/__init__.py Thu Apr 15 12:47:02 2010 +0200
+++ b/devtools/__init__.py Thu Apr 15 12:48:40 2010 +0200
@@ -214,8 +214,10 @@
driver = config.sources()['system']['db-driver']
if driver == 'sqlite':
reset_test_database_sqlite(config)
- elif driver == 'sqlserver2005':
- reset_test_database_sqlserver2005(config)
+ elif driver in ('sqlserver2005', 'postgres'):
+ # XXX do something with dump/restore ?
+ print 'resetting the database is not done for', driver
+ print 'you should handle it manually'
else:
raise ValueError('no reset function for driver %r' % driver)
@@ -236,9 +238,6 @@
from cubicweb.server import init_repository
init_repository(config, interactive=False, drop=True, vreg=vreg)
-def reset_test_database_sqlserver2005(config):
- pass
-
### sqlite test database handling ##############################################
def cleanup_sqlite(dbfile, removetemplate=False):
--- a/devtools/testlib.py Thu Apr 15 12:47:02 2010 +0200
+++ b/devtools/testlib.py Thu Apr 15 12:48:40 2010 +0200
@@ -134,6 +134,7 @@
class CubicWebTC(TestCase):
"""abstract class for test using an apptest environment
+
attributes:
* `vreg`, the vregistry
@@ -145,7 +146,6 @@
* `repo`, the repository object
* `admlogin`, login of the admin user
* `admpassword`, password of the admin user
-
"""
appid = 'data'
configcls = devtools.ApptestConfiguration
--- a/doc/book/en/admin/index.rst Thu Apr 15 12:47:02 2010 +0200
+++ b/doc/book/en/admin/index.rst Thu Apr 15 12:48:40 2010 +0200
@@ -2,9 +2,9 @@
.. _Part3:
--------------------------
-Part III - Administration
--------------------------
+--------------
+Administration
+--------------
This part is for installation and administration of the *CubicWeb* framework and
instances based on that framework.
--- a/doc/book/en/admin/setup.rst Thu Apr 15 12:47:02 2010 +0200
+++ b/doc/book/en/admin/setup.rst Thu Apr 15 12:48:40 2010 +0200
@@ -141,6 +141,15 @@
Please be careful to select the right python (2.5) and postgres (8.4) versions.
+A windows compiled recent version of gettext::
+
+ http://ftp.logilab.org/pub/gettext/gettext-0.17-win32-setup.exe
+
+A pre-compiled version of rql for windows (take care of retrieving the
+most recent version available there)::
+
+ http://ftp.logilab.org/pub/rql/rql-0.23.0.win32-py2.5.exe
+
Pyro enables remote access to cubicweb repository instances. Get it there::
http://sourceforge.net/projects/pyro/files/
--- a/doc/book/en/annexes/index.rst Thu Apr 15 12:47:02 2010 +0200
+++ b/doc/book/en/annexes/index.rst Thu Apr 15 12:48:40 2010 +0200
@@ -2,9 +2,9 @@
.. _Part4:
---------------------
-Part IV - Appendixes
---------------------
+----------
+Appendixes
+----------
The following chapters are reference material.
--- a/doc/book/en/conf.py Thu Apr 15 12:47:02 2010 +0200
+++ b/doc/book/en/conf.py Thu Apr 15 12:48:40 2010 +0200
@@ -32,10 +32,10 @@
# Add any Sphinx extension module names here, as strings. They can be extensions
# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
-extensions = ['sphinx.ext.autodoc', 'logilab.common.sphinx_ext']#, 'sphinxcontrib.aafig']
+extensions = ['sphinx.ext.autodoc', 'logilab.common.sphinx_ext']
autoclass_content = 'both'
# Add any paths that contain templates here, relative to this directory.
-templates_path = ['.templates']
+#templates_path = []
# The suffix of source filenames.
source_suffix = '.rst'
@@ -97,8 +97,8 @@
# The name for this set of Sphinx documents. If None, it defaults to
# "<project> v<release> documentation".
html_title = '%s %s' % (project, release)
-html_theme = 'lglb_doc'
-html_theme_path = ['_theme']
+html_theme = 'standard_theme'
+html_theme_path = ['.']
# A shorter title for the navigation bar. Default is the same as html_title.
#html_short_title = None
@@ -189,4 +189,3 @@
# If false, no module index is generated.
#latex_use_modindex = True
#aafig_format = dict(latex='pdf', html='svg', text=None)
-
--- a/doc/book/en/development/devcore/cwconfig.rst Thu Apr 15 12:47:02 2010 +0200
+++ b/doc/book/en/development/devcore/cwconfig.rst Thu Apr 15 12:48:40 2010 +0200
@@ -1,5 +1,5 @@
-:mod:`Configuration <cubicweb.cwconfig>`
-----------------------------------------
+Configuration
+-------------
-.. .. automodule:: cubicweb.cwconfig
-.. :members:
+.. automodule:: cubicweb.cwconfig
+ :members:
--- a/doc/book/en/development/devcore/dbapi.rst Thu Apr 15 12:47:02 2010 +0200
+++ b/doc/book/en/development/devcore/dbapi.rst Thu Apr 15 12:48:40 2010 +0200
@@ -8,6 +8,7 @@
The most important method is the `execute` method of a cursor.
.. sourcecode:: python
+
execute(rqlstring, args=None, cachekey=None, build_descr=True)
:rqlstring: the RQL query to execute (unicode)
--- a/doc/book/en/development/devcore/reqbase.rst Thu Apr 15 12:47:02 2010 +0200
+++ b/doc/book/en/development/devcore/reqbase.rst Thu Apr 15 12:48:40 2010 +0200
@@ -1,3 +1,5 @@
+Request and ResultSet methods
+-----------------------------
Those are methods you'll find on both request objects and on repository session:
--- a/doc/book/en/development/devrepo/hooks.rst Thu Apr 15 12:47:02 2010 +0200
+++ b/doc/book/en/development/devrepo/hooks.rst Thu Apr 15 12:48:40 2010 +0200
@@ -320,6 +320,11 @@
* when several hooks need to instantiate the same operation (e.g. an
entity and a relation hook).
+.. note::
+
+ A more realistic example can be found in the advanced tutorial
+ chapter :ref:`adv_tuto_security_propagation`.
+
Operation: a small API overview
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
--- a/doc/book/en/development/devweb/controllers.rst Thu Apr 15 12:47:02 2010 +0200
+++ b/doc/book/en/development/devweb/controllers.rst Thu Apr 15 12:48:40 2010 +0200
@@ -1,3 +1,5 @@
+.. _controllers:
+
Controllers
-----------
@@ -10,7 +12,7 @@
The following controllers are provided out-of-the box in CubicWeb. We
list them by category.
-Browsing:
+`Browsing`:
* the View controller (web/views/basecontrollers.py) is associated
with most browsing actions within a CubicWeb application: it always
@@ -27,9 +29,9 @@
* the Login/Logout controllers (web/views/basecontrollers.py) make
effective user login or logout requests
-Edition:
+`Edition`:
-* the Edit controller (web/views/editcontroller.py) handles CRUD
+* the Edit controller (see :ref:`edit_controller`) handles CRUD
operations in response to a form being submitted; it works in close
association with the Forms, to which it delegates some of the work
@@ -40,7 +42,7 @@
Form validator controller, and the UI is decorated with failure
information, either global or per-field , until it is valid)
-Other:
+`Other`:
* the SendMail controller (web/views/basecontrollers.py) is reponsible
for outgoing email notifications
@@ -76,4 +78,122 @@
process.
+.. _edit_controller:
+The `edit controller`
++++++++++++++++++++++
+
+It can be found in (:mod:`cubicweb.web.views.editcontroller`).
+
+Editing control
+~~~~~~~~~~~~~~~~
+
+Re-requisites: the parameters related to entities to edit are
+specified as follows ::
+
+ <field name>:<entity eid>
+
+where entity eid could be a letter in case of an entity to create. We
+name those parameters as *qualified*.
+
+1. Retrieval of entities to edit by looking for the forms parameters
+ starting by `eid:` and also having a parameter `__type` associated
+ (also *qualified* by eid)
+
+2. For all the attributes and the relations of an entity to edit:
+
+ 1. search for a parameter `edits-<relation name>` or `edito-<relation name>`
+ qualified in the case of a relation where the entity is object
+ 2. if found, the value returned is considered as the initial value
+ for this relaiton and we then look for the new value(s) in the parameter
+ <relation name> (qualified)
+ 3. if the value returned is different from the initial value, an database update
+ request is done
+
+3. For each entity to edit:
+
+ 1. if a qualified parameter `__linkto` is specified, its value has to be
+ a string (or a list of string) such as: ::
+
+ <relation type>:<eids>:<target>
+
+ where <target> is either `subject` or `object` and each eid could be
+ separated from the others by a `_`. Target specifies if the *edited entity*
+ is subject or object of the relation and each relation specified will
+ be inserted.
+
+ 2. if a qualified parameter `__clone_eid` is specified for an entity, the
+ relations of the specified entity passed as value of this parameter are
+ copied on the edited entity.
+
+ 3. if a qualified parameter `__delete` is specified, its value must be
+ a string or a list of string such as follows: ::
+
+ <ssubjects eids>:<relation type>:<objects eids>
+
+ where each eid subject or object can be seperated from the other
+ by `_`. Each relation specified will be deleted.
+
+ 4. if a qualified parameter `__insert` is specified, its value should
+ follow the same pattern as `__delete`, but each relation specified is
+ inserted.
+
+4. If the parameters `__insert` and/or `__delete` are found not qualified,
+ they are interpreted as explained above (independantly from the number
+ of entities edited).
+
+5. If no entity is edited but the form contains the parameters `__linkto`
+ and `eid`, this one is interpreted by using the value specified for `eid`
+ to designate the entity on which to add the relations.
+
+
+.. note::
+
+ * If the parameter `__action_delete` is found, all the entities specified
+ as to be edited will be deleted.
+
+ * If the parameter `__action_cancel` is found, no action is completed.
+
+ * If the parameter `__action_apply` is found, the editing is
+ applied normally but the redirection is done on the form (see
+ :ref:`RedirectionControl`).
+
+ * The parameter `__method` is also supported as for the main template
+
+ * If no entity is found to be edited and if there is no parameter
+ `__action_delete`, `__action_cancel`, `__linkto`, `__delete` or
+ `__insert`, an error is raised.
+
+ * Using the parameter `__message` in the form will allow to use its value
+ as a message to provide the user once the editing is completed.
+
+
+.. _RedirectionControl:
+
+Redirection control
+~~~~~~~~~~~~~~~~~~~
+Once editing is completed, there is still an issue left: where should we go
+now? If nothing is specified, the controller will do his job but it does not
+mean we will be happy with the result. We can control that by using the
+following parameters:
+
+* `__redirectpath`: path of the URL (relative to the root URL of the site,
+ no form parameters
+
+* `__redirectparams`: forms parameters to add to the path
+
+* `__redirectrql`: redirection RQL request
+
+* `__redirectvid`: redirection view identifier
+
+* `__errorurl`: initial form URL, used for redirecting in case a validation
+ error is raised during editing. If this one is not specified, an error page
+ is displayed instead of going back to the form (which is, if necessary,
+ responsible for displaying the errors)
+
+* `__form_id`: initial view form identifier, used if `__action_apply` is
+ found
+
+In general we use either `__redirectpath` and `__redirectparams` or
+`__redirectrql` and `__redirectvid`.
+
--- a/doc/book/en/development/devweb/index.rst Thu Apr 15 12:47:02 2010 +0200
+++ b/doc/book/en/development/devweb/index.rst Thu Apr 15 12:48:40 2010 +0200
@@ -4,14 +4,14 @@
In this chapter, we will describe the core api for web development in the *CubicWeb* framework.
.. toctree::
- :maxdepth: 1
+ :maxdepth: 2
request
publisher
controllers
property
rtags
- views
+ views/index
form
facets
httpcaching
--- a/doc/book/en/development/devweb/rtags.rst Thu Apr 15 12:47:02 2010 +0200
+++ b/doc/book/en/development/devweb/rtags.rst Thu Apr 15 12:48:40 2010 +0200
@@ -1,14 +1,21 @@
Configuring the user interface
------------------------------
+.. _relation_tags:
Relation tags
~~~~~~~~~~~~~
.. automodule:: cubicweb.rtags
-
+.. _uicfg_module:
The ``uicfg`` module
~~~~~~~~~~~~~~~~~~~~
+
+.. note::
+
+ The part of uicfg that deals with primary views is in the
+ :ref:`primary_view_configuration` chapter.
+
.. automodule:: cubicweb.web.uicfg
--- a/doc/book/en/development/devweb/views.rst Thu Apr 15 12:47:02 2010 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,267 +0,0 @@
-
-.. _Views:
-
-Views
------
-
-This chapter aims to describe the concept of a `view` used all along
-the development of a web application and how it has been implemented
-in *CubicWeb*.
-
-We'll start with a description of the interface providing you with a basic
-understanding of the available classes and methods, then detail the view
-selection principle which makes *CubicWeb* web interface very flexible.
-
-A `View` is an object applied to another object such as an entity.
-
-Basic class for views
-~~~~~~~~~~~~~~~~~~~~~
-
-Class `View` (`cubicweb.view`)
-`````````````````````````````````````
-
-This class is an abstraction of a view class, used as a base class for every
-renderable object such as views, templates, graphic components, etc.
-
-A `View` is instantiated to render a result set or part of a result set. `View`
-subclasses may be parametrized using the following class attributes:
-
-* `templatable` indicates if the view may be embedded in a main
- template or if it has to be rendered standalone (i.e. XML views must
- not be embedded in the main template for HTML pages)
-
-* if the view is not templatable, it should set the `content_type`
- class attribute to the correct MIME type (text/xhtml by default)
-
-* the `category` attribute may be used in the interface to regroup
- related objects together
-
-A view writes to its output stream thanks to its attribute `w` (an
-`UStreamIO`, except for binary views).
-
-At instantiation time, the standard `_cw` and `cw_rset` attributes are
-added and the `w` attribute will be set at rendering time.
-
-The basic interface for views is as follows (remember that the result set has a
-tabular structure with rows and columns, hence cells):
-
-* `render(**context)`, render the view by calling `call` or
- `cell_call` depending on the given parameters
-
-* `call(**kwargs)`, call the view for a complete result set or null
- (the default implementation calls `cell_call()` on each cell of the
- result set)
-
-* `cell_call(row, col, **kwargs)`, call the view for a given cell of a
- result set (`row` and `col` being integers used to access the cell)
-
-* `url()`, returns the URL enabling us to get the view with the current
- result set
-
-* `wview(__vid, rset, __fallback_vid=None, **kwargs)`, call the view of
- identifier `__vid` on the given result set. It is possible to give a
- fallback view identifier that will be used if the requested view is
- not applicable to the result set.
-
-* `html_headers()`, returns a list of HTML headers to be set by the
- main template
-
-* `page_title()`, returns the title to use in the HTML header `title`
-
-Other basic view classes
-````````````````````````
-Here are some of the subclasses of `View` defined in `cubicweb.common.view`
-that are more concrete as they relate to data rendering within the application:
-
-* `EntityView`, view applying to lines or cell containing an entity (e.g. an eid)
-* `StartupView`, start view that does not require a result set to apply to
-* `AnyRsetView`, view applicable to any result set
-
-Examples of views class
------------------------
-
-- Using `templatable`, `content_type` and HTTP cache configuration
-
-.. sourcecode:: python
-
- class RSSView(XMLView):
- __regid__ = 'rss'
- title = _('rss')
- templatable = False
- content_type = 'text/xml'
- http_cache_manager = MaxAgeHTTPCacheManager
- cache_max_age = 60*60*2 # stay in http cache for 2 hours by default
-
-
-- Using custom selector
-
-.. sourcecode:: python
-
- class SearchForAssociationView(EntityView):
- """view called by the edition view when the user asks
- to search for something to link to the edited eid
- """
- __regid__ = 'search-associate'
- title = _('search for association')
- __select__ = one_line_rset() & match_search_state('linksearch') & implements('Any')
-
-
-
-Example of view customization and creation
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-We'll show you now an example of a ``primary`` view and how to customize it.
-
-If you want to change the way a ``BlogEntry`` is displayed, just override
-the method ``cell_call()`` of the view ``primary`` in ``BlogDemo/views.py``:
-
-.. sourcecode:: python
-
- from cubicweb.selectors import implements
- from cubicweb.web.views.primary improt Primaryview
-
- class BlogEntryPrimaryView(PrimaryView):
- __select__ = PrimaryView.__select__ & implements('BlogEntry')
-
- def render_entity_attributes(self, entity):
- self.w(u'<p>published on %s</p>' %
- entity.publish_date.strftime('%Y-%m-%d'))
- super(BlogEntryPrimaryView, self).render_entity_attributes(entity)
-
-The above source code defines a new primary view for
-``BlogEntry``. The `id` class attribute is not repeated there since it
-is inherited through the `primary.PrimaryView` class.
-
-The selector for this view chains the selector of the inherited class
-with its own specific criterion.
-
-The view method ``self.w()`` is used to output data. Here `lines
-08-09` output HTML for the publication date of the entry.
-
-.. image:: ../../images/lax-book.09-new-view-blogentry.en.png
- :alt: blog entries now look much nicer
-
-Let us now improve the primary view of a blog
-
-.. sourcecode:: python
-
- from logilab.mtconverter import xml_escape
- from cubicweb.selectors import implements, one_line_rset
- from cubicweb.web.views.primary import Primaryview
-
- class BlogPrimaryView(PrimaryView):
- __regid__ = 'primary'
- __select__ = PrimaryView.__select__ & implements('Blog')
- rql = 'Any BE ORDERBY D DESC WHERE BE entry_of B, BE publish_date D, B eid %(b)s'
-
- def render_entity_relations(self, entity):
- rset = self._cw.execute(self.rql, {'b' : entity.eid})
- for entry in rset.entities():
- self.w(u'<p>%s</p>' % entry.view('inblogcontext'))
-
- class BlogEntryInBlogView(EntityView):
- __regid__ = 'inblogcontext'
- __select__ = implements('BlogEntry')
-
- def cell_call(self, row, col):
- entity = self.cw_rset.get_entity(row, col)
- self.w(u'<a href="%s" title="%s">%s</a>' %
- entity.absolute_url(),
- xml_escape(entity.content[:50]),
- xml_escape(entity.description))
-
-This happens in two places. First we override the
-render_entity_relations method of a Blog's primary view. Here we want
-to display our blog entries in a custom way.
-
-At `line 10`, a simple request is made to build a result set with all
-the entities linked to the current ``Blog`` entity by the relationship
-``entry_of``. The part of the framework handling the request knows
-about the schema and infers that such entities have to be of the
-``BlogEntry`` kind and retrieves them (in the prescribed publish_date
-order).
-
-The request returns a selection of data called a result set. Result
-set objects have an .entities() method returning a generator on
-requested entities (going transparently through the `ORM` layer).
-
-At `line 13` the view 'inblogcontext' is applied to each blog entry to
-output HTML. (Note that the 'inblogcontext' view is not defined
-whatsoever in *CubicWeb*. You are absolutely free to define whole view
-families.) We juste arrange to wrap each blogentry output in a 'p'
-html element.
-
-Next, we define the 'inblogcontext' view. This is NOT a primary view,
-with its well-defined sections (title, metadata, attribtues,
-relations/boxes). All a basic view has to define is cell_call.
-
-Since views are applied to result sets which can be tables of data, we
-have to recover the entity from its (row,col)-coordinates (`line
-20`). Then we can spit some HTML.
-
-But careful: all strings manipulated in *CubicWeb* are actually
-unicode strings. While web browsers are usually tolerant to incoherent
-encodings they are being served, we should not abuse it. Hence we have
-to properly escape our data. The xml_escape() function has to be used
-to safely fill (X)HTML elements from Python unicode strings.
-
-
-**This is to be compared to interfaces and protocols in object-oriented
-languages. Applying a given view called 'a_view' to all the entities
-of a result set only requires to have for each entity of this result set,
-an available view called 'a_view' which accepts the entity.**
-
-**Instead of merely using type based dispatch, we do predicate dispatch
-which is quite more powerful.**
-
-Assuming we added entries to the blog titled `MyLife`, displaying it
-now allows to read its description and all its entries.
-
-.. image:: ../../images/lax-book.10-blog-with-two-entries.en.png
- :alt: a blog and all its entries
-
-**Before we move forward, remember that the selection/view principle is
-at the core of *CubicWeb*. Everywhere in the engine, data is requested
-using the RQL language, then HTML/XML/text/PNG is output by applying a
-view to the result set returned by the query. That is where most of the
-flexibility comes from.**
-
-[WRITE ME]
-
-* implementing interfaces, calendar for blog entries
-* show that a calendar view can export data to ical
-
-We will implement the `cubicweb.interfaces.ICalendarable` interfaces on
-entities.BlogEntry and apply the OneMonthCalendar and iCalendar views
-to result sets like "Any E WHERE E is BlogEntry"
-
-* create view "blogentry table" with title, publish_date, category
-
-We will show that by default the view that displays
-"Any E,D,C WHERE E publish_date D, E category C" is the table view.
-Of course, the same can be obtained by calling
-self.wview('table',rset)
-
-* in view blog, select blogentries and apply view "blogentry table"
-* demo ajax by filtering blogentry table on category
-
-we did the same with 'primary', but with tables we can turn on filters
-and show that ajax comes for free.
-[FILLME]
-
-
-XML views, binaries views...
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-For views generating other formats than HTML (an image generated dynamically
-for example), and which can not simply be included in the HTML page generated
-by the main template (see above), you have to:
-
-* set the attribute `templatable` of the class to `False`
-* set, through the attribute `content_type` of the class, the MIME type generated
- by the view to `application/octet-stream`
-
-For views dedicated to binary content creation (like dynamically generated
-images), we have to set the attribute `binary` of the class to `True` (which
-implies that `templatable == False`, so that the attribute `w` of the view could be
-replaced by a binary flow instead of unicode).
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/book/en/development/devweb/views/autoform.rst Thu Apr 15 12:48:40 2010 +0200
@@ -0,0 +1,69 @@
+The automatic entity form (:mod:`cubicweb.web.views.autoform`)
+---------------------------------------------------------------
+
+Tags declaration
+~~~~~~~~~~~~~~~~~~~~
+
+It is possible to manage attributes/relations in the simple or multiple
+editing form thanks of the methods bellow ::
+
+ uicfg.autoform_section.tag_subject_of(<relation>, tag)
+ uicfg.autoform_section.tag_object_of(<relation>, tag)
+ uicfg.autoform_field.tag_attribute(<attribut_def>, tag)
+
+Where ``<relation>`` is a three elements tuple ``(Subject Entity Type,
+relation_type, Object Entity Type)``. ``<attribut_def>`` is a two elements tuple
+``(Entity Type, Attribut Name)``. Wildcard ``*`` could be used in place of
+``Entity Type``
+
+Possible tags are detailled below
+
+Simple Tags
+~~~~~~~~~~~~~~~~~~~~
+
+* `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 and represented as a combobox. Each item of the
+ combobox is a link to an existing entity.
+
+* `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 will be included in the
+ editing form and represented as a combobox. Each item of the combobox
+ is a link to an existing entity.
+
+* `inlineview`, includes the target entity's form in the editing form
+ of the current entity. It allows to create the target entity in the
+ same time as the current entity.
+
+* `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 necessary, it is possible to overwrite the method
+`relation_category(rtype, x='subject')` to dynamically compute
+a relation editing category.
+
+
+Advanced Tags
+~~~~~~~~~~~~~~~~~~~~
+
+Tag can also reference a custom Field crafted with the help of
+``cubicweb.web.formfields`` and ``cubicweb.web.formwidget``. In the example
+bellow, the field ``path`` of ``ExecData`` entities will be done with a standard
+file input dialogue ::
+
+ from cubicweb.web import uicfg, formfields, formwidgets
+
+ uicfg.autoform_field.tag_attribute(('Execdata', 'path'),
+ formfields.FileField(name='path', widget=formwidgets.FileInput()))
+
+
+
+
+
+
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/book/en/development/devweb/views/basetemplates.rst Thu Apr 15 12:48:40 2010 +0200
@@ -0,0 +1,189 @@
+.. -*- coding: utf-8 -*-
+
+.. _templates:
+
+Templates
+=========
+
+[WRITE ME]
+
+* talk about main templates, etc.
+
+
+
+Look at ``cubicweb/web/views/basetemplates.py`` and you will
+find the base templates used to generate HTML for your application.
+
+A page is composed as indicated on the schema below :
+
+.. image:: ../../../images/main_template.png
+
+In this section we will go through a couple of the primary templates
+you must be interested in, that is to say, the HTMLPageHeader,
+the HTMLPageFooter and the TheMainTemplate.
+
+
+HTMLPageHeader
+--------------
+
+Customize header
+~~~~~~~~~~~~~~~~
+
+Let's now move the search box in the header and remove the login form
+from the header. We'll show how to move it to the left column of the application.
+
+Let's say we do not want anymore the login menu to be in the header, but we
+prefer it to be in the left column just below the logo. As the left column is
+rendered by ``TheMainTemplate``, we will show how to do it in TheMainTemplate_.
+
+First, to remove the login menu, we just need to comment out the display of the
+login component such as follows : ::
+
+ class MyHTMLPageHeader(HTMLPageHeader):
+
+ def main_header(self, view):
+ """build the top menu with authentification info and the rql box"""
+ self.w(u'<table id="header"><tr>\n')
+ self.w(u'<td id="firstcolumn">')
+ self._cw.vreg.select_component('logo', self._cw, self.cw_rset).dispatch(w=self.w)
+ self.w(u'</td>\n')
+ # appliname and breadcrumbs
+ self.w(u'<td id="headtext">')
+ comp = self._cw.vreg.select_component('appliname', self._cw, self.cw_rset)
+ if comp and comp.propval('visible'):
+ comp.dispatch(w=self.w)
+ comp = self._cw.vreg.select_component('breadcrumbs', self._cw, self.cw_rset, view=view)
+ if comp and comp.propval('visible'):
+ comp.dispatch(w=self.w, view=view)
+ self.w(u'</td>')
+ # logged user and help
+ #self.w(u'<td>\n')
+ #comp = self._cw.vreg.select_component('loggeduserlink', self._cw, self.cw_rset)
+ #comp.dispatch(w=self.w)
+ #self.w(u'</td><td>')
+
+ self.w(u'<td>')
+ helpcomp = self._cw.vreg.select_component('help', self._cw, self.cw_rset)
+ if helpcomp: # may not be available if Card is not defined in the schema
+ helpcomp.dispatch(w=self.w)
+ self.w(u'</td>')
+ # lastcolumn
+ self.w(u'<td id="lastcolumn">')
+ self.w(u'</td>\n')
+ self.w(u'</tr></table>\n')
+ self.template('logform', rset=self.cw_rset, id='popupLoginBox', klass='hidden',
+ title=False, message=False)
+
+
+
+.. image:: ../../../images/lax-book.06-header-no-login.en.png
+
+Let's now move the search box in the top-right header area. To do so, we will
+first create a method to get the search box display and insert it in the header
+table.
+
+::
+
+ from cubicweb.web.views.basetemplates import HTMLPageHeader
+ class MyHTMLPageHeader(HTMLPageHeader):
+ def main_header(self, view):
+ """build the top menu with authentification info and the rql box"""
+ self.w(u'<table id="header"><tr>\n')
+ self.w(u'<td id="firstcolumn">')
+ self._cw.vreg.select_component('logo', self._cw, self.cw_rset).dispatch(w=self.w)
+ self.w(u'</td>\n')
+ # appliname and breadcrumbs
+ self.w(u'<td id="headtext">')
+ comp = self._cw.vreg.select_component('appliname', self._cw, self.cw_rset)
+ if comp and comp.propval('visible'):
+ comp.dispatch(w=self.w)
+ comp = self._cw.vreg.select_component('breadcrumbs', self._cw, self.cw_rset, view=view)
+ if comp and comp.propval('visible'):
+ comp.dispatch(w=self.w, view=view)
+ self.w(u'</td>')
+
+ # logged user and help
+ #self.w(u'<td>\n')
+ #comp = self._cw.vreg.select_component('loggeduserlink', self._cw, self.cw_rset)
+ #comp.dispatch(w=self.w)
+ #self.w(u'</td><td>')
+
+ # search box
+ self.w(u'<td>')
+ self.get_searchbox(view, 'left')
+ self.w(u'</td>')
+
+ self.w(u'<td>')
+ helpcomp = self._cw.vreg.select_component('help', self._cw, self.cw_rset)
+ if helpcomp: # may not be available if Card is not defined in the schema
+ helpcomp.dispatch(w=self.w)
+ self.w(u'</td>')
+ # lastcolumn
+ self.w(u'<td id="lastcolumn">')
+ self.w(u'</td>\n')
+ self.w(u'</tr></table>\n')
+ self.template('logform', rset=self.cw_rset, id='popupLoginBox', klass='hidden',
+ title=False, message=False)
+
+ def get_searchbox(self, view, context):
+ boxes = list(self._cw.vreg.poss_visible_objects('boxes', self._cw, self.cw_rset,
+ view=view, context=context))
+ if boxes:
+ for box in boxes:
+ if box.__regid__ == 'search_box':
+ box.dispatch(w=self.w, view=view)
+
+
+
+
+HTMLPageFooter
+--------------
+
+If you want to change the footer for example, look
+for HTMLPageFooter and override it in your views file as in :
+::
+
+ form cubicweb.web.views.basetemplates import HTMLPageFooter
+ class MyHTMLPageFooter(HTMLPageFooter):
+ def call(self, **kwargs):
+ self.w(u'<div class="footer">')
+ self.w(u'This website has been created with <a href="http://cubicweb.org">CubicWeb</a>.')
+ self.w(u'</div>')
+
+Updating a view does not require any restart of the server. By reloading
+the page you can see your new page footer.
+
+
+TheMainTemplate
+---------------
+.. _TheMainTemplate:
+
+TheMainTemplate is responsible for the general layout of the entire application.
+It defines the template of ``__regid__ = main`` that is used by the instance.
+
+The default main template (`cubicweb.web.views.basetemplates.TheMainTemplate`)
+builds the page based on the following pattern:
+
+.. image:: ../../../images/main_template_layout.png
+
+The rectangle containing `view.dispatch()` represents the area where the content
+view has to be displayed. The others represents sub-templates called to complete
+the page. A default implementation of those is provided in
+`cubicweb.views.basetemplates`. You can, of course, overload those sub-templates
+to implement your own customization of the HTML page.
+
+We can also control certain aspects of the main template thanks to the following
+forms parameters:
+
+* `__notemplate`, if present (whatever the value assigned), only the content view
+ is returned
+* `__force_display`, if present and its value is not null, no navigation
+ whatever the number of entities to display
+* `__method`, if the result set to render contains only one entity and this
+ parameter is set, it refers to a method to call on the entity by passing it
+ the dictionary of the forms parameters, before going the classic way (through
+ step 1 and 2 described juste above)
+
+The MainTemplate is a bit complex as it tries to accomodate many
+different cases. We are now about to go through it and cutomize entirely
+our application.
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/book/en/development/devweb/views/baseviews.rst Thu Apr 15 12:48:40 2010 +0200
@@ -0,0 +1,78 @@
+.. -*- coding: utf-8 -*-
+
+Base views (:mod:`cubicweb.web.views.baseviews`)
+------------------------------------------------
+
+*CubicWeb* provides a lot of standard views. You can find them in
+``cubicweb/web/views/``.
+
+A certain number of views are used to build the web interface, which apply
+to one or more entities. Their identifier is what distinguish them from
+each others and the main ones are:
+
+HTML views
+~~~~~~~~~~
+
+Special views
+`````````````
+
+*noresult*
+ This view is the default view used when no result has been found
+ (e.g. empty result set).
+
+*final*
+ Display the value of a cell without trasnformation (in case of a non final
+ entity, we see the eid). Applicable on any result set.
+
+*null*
+ This view is the default view used when nothing needs to be rendered.
+ It is always applicable and it does not return anything
+
+Entity views
+````````````
+*incontext, outofcontext*
+ Those are used to display a link to an entity, depending on the
+ entity having to be displayed in or out of context
+ (of another entity). By default it respectively returns the
+ result of `textincontext` and `textoutofcontext` wrapped in a link
+ leading to the primary view of the entity.
+
+*oneline*
+ This view is used when we can't tell if the entity should be considered as
+ displayed in or out of context. By default it returns the result of `text`
+ in a link leading to the primary view of the entity.
+
+List
+`````
+
+*list*
+ This view displays a list of entities by creating a HTML list (`<ul>`)
+ and call the view `listitem` for each entity of the result set.
+
+*listitem*
+ This view redirects by default to the `outofcontext` view.
+
+*sameetypelist*
+ This view displays a list of entities of the same type, in HTML section (`<div>`)
+ and call the view `sameetypelistitem` for each entity of the result set.
+
+*sameetypelistitem*
+ This view redirects by default to the `listitem` view.
+
+*csv*
+ This view applies to entity groups, which are individually
+ displayed using the `incontext` view. It displays each entity as a
+ coma separated list. It is NOT related to the well-known text file
+ format.
+
+Text entity views
+~~~~~~~~~~~~~~~~~
+*text*
+ This is the simplest text view for an entity. By default it returns the
+ result of the `.dc_title` method, which is cut to fit the
+ `navigation.short-line-size` property if necessary.
+
+*textincontext, textoutofcontext*
+ Similar to the `text` view, but called when an entity is considered out or
+ in context. By default it returns respectively the result of the
+ methods `.dc_title` and `.dc_long_title` of the entity.
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/book/en/development/devweb/views/boxes.rst Thu Apr 15 12:48:40 2010 +0200
@@ -0,0 +1,34 @@
+Boxes (:mod:`cubicweb.web.views.boxes`)
+---------------------------------------------------------------
+
+*sidebox*
+ This view displays usually a side box of some related entities
+ in a primary view.
+
+The action box
+~~~~~~~~~~~~~~~
+
+The ``add_related`` is an automatic menu in the action 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 explicitly specify them thanks to the
+`cubicweb.web.uicfg.rmode` *relation tag*:
+
+* `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 necessary, 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).
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/book/en/development/devweb/views/breadcrumbs.rst Thu Apr 15 12:48:40 2010 +0200
@@ -0,0 +1,3 @@
+Breadcrumbs (:mod:`cubicweb.web.views.ibreadcrumbs`)
+----------------------------------------------------
+XXX feedme
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/book/en/development/devweb/views/editforms.rst Thu Apr 15 12:48:40 2010 +0200
@@ -0,0 +1,3 @@
+Standard forms (:mod:`cubicweb.web.views.editforms`)
+----------------------------------------------------
+XXX feed me
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/book/en/development/devweb/views/embedding.rst Thu Apr 15 12:48:40 2010 +0200
@@ -0,0 +1,9 @@
+.. -*- coding: utf-8 -*-
+
+Embedding external pages (:mod:`cubicweb.web.views.embedding`)
+---------------------------------------------------------------
+
+including external content
+
+XXX feeed me
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/book/en/development/devweb/views/facets.rst Thu Apr 15 12:48:40 2010 +0200
@@ -0,0 +1,3 @@
+Facets (:mod:`cubicweb.web.views.facets`)
+-----------------------------------------
+XXX feed me
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/book/en/development/devweb/views/idownloadable.rst Thu Apr 15 12:48:40 2010 +0200
@@ -0,0 +1,3 @@
+The 'download' view (:mod:`cubicweb.web.views.idownloadable`)
+---------------------------------------------------------------
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/book/en/development/devweb/views/index.rst Thu Apr 15 12:48:40 2010 +0200
@@ -0,0 +1,30 @@
+The views system
+================
+
+.. |cubicweb| replace:: *CubicWeb*
+
+This chapter aims to describe the concept of a `view` used all along
+the development of a web application and how it has been implemented
+in |cubicweb|.
+
+
+.. toctree::
+ :maxdepth: 3
+
+ views
+ basetemplates
+ primary
+ baseviews
+ startup
+ boxes
+ table
+ xmlrss
+ autoform
+ editforms
+ urlpublish
+ breadcrumbs
+ facets
+ wdoc
+ embedding
+ idownloadable
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/book/en/development/devweb/views/primary.rst Thu Apr 15 12:48:40 2010 +0200
@@ -0,0 +1,312 @@
+.. _primary_view:
+
+The Primary View
+-----------------
+
+(:mod:`cubicweb.web.views.primary`)
+
+By default, *CubicWeb* provides a view that fits every available
+entity type. This is the first view you might be interested in
+modifying. It is also one of the richest and most complex.
+
+It is automatically selected on a one line result set containing an
+entity.
+
+This view is supposed to render a maximum of informations about the
+entity.
+
+.. _primary_view_layout:
+
+Layout
+``````
+
+The primary view has the following layout.
+
+.. image:: ../../../images/primaryview_template.png
+
+.. _primary_view_configuration:
+
+Primary view configuration
+``````````````````````````
+
+If you want to customize the primary view of an entity, overriding the primary
+view class may not be necessary. For simple adjustments (attributes or relations
+display locations and styles), a much simpler way is to use uicfg.
+
+Attributes/relations display location
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+In the primary view, there are 3 sections where attributes and
+relations can be displayed (represented in pink in the image above):
+
+* attributes
+* relations
+* sideboxes
+
+**Attributes** can only be displayed in the attributes section (default
+ behavior). They can also be hidden.
+
+For instance, to hide the ``title`` attribute of the ``Blog`` entity:
+
+.. sourcecode:: python
+
+ from cubicweb.web import uicfg
+ uicfg.primaryview_section.tag_attribute(('Blog', 'title'), 'hidden')
+
+**Relations** can be either displayed in one of the three sections or hidden.
+
+For relations, there are two methods:
+
+* ``tag_object_of`` for modifying the primary view of the object
+* ``tag_subject_of`` for modifying the primary view of the subject
+
+These two methods take two arguments:
+
+* a triplet ``(subject, relation_name, object)``, where subject or object can be replaced with ``'*'``
+* the section name or ``hidden``
+
+.. sourcecode:: python
+
+ pv_section = uicfg.primaryview_section
+ # hide every relation `entry_of` in the `Blog` primary view
+ pv_section.tag_object_of(('*', 'entry_of', 'Blog'), 'hidden')
+
+ # display `entry_of` relations in the `relations`
+ # section in the `BlogEntry` primary view
+ pv_section.tag_subject_of(('BlogEntry', 'entry_of', '*'), 'relations')
+
+
+Display content
+^^^^^^^^^^^^^^^
+
+You can use ``primaryview_display_ctrl`` to customize the display of attributes
+or relations. Values of ``primaryview_display_ctrl`` are dictionaries.
+
+
+Common keys for attributes and relations are:
+
+* ``vid``: specifies the regid of the view for displaying the attribute or the relation.
+
+ If ``vid`` is not specified, the default value depends on the section:
+ * ``attributes`` section: 'reledit' view
+ * ``relations`` section: 'autolimited' view
+ * ``sideboxes`` section: 'sidebox' view
+
+* ``order``: int used to control order within a section. When not specified,
+ automatically set according to order in which tags are added.
+
+.. sourcecode:: python
+
+ # let us remind the schema of a blog entry
+ class BlogEntry(EntityType):
+ title = String(required=True, fulltextindexed=True, maxsize=256)
+ publish_date = Date(default='TODAY')
+ content = String(required=True, fulltextindexed=True)
+ entry_of = SubjectRelation('Blog', cardinality='?*')
+
+ # now, we want to show attributes
+ # with an order different from that in the schema definition
+ view_ctrl = uicfg.primaryview_display_ctrl
+ for index, attr in enumerate('title', 'content', 'publish_date'):
+ view_ctrl.tag_attribute(('BlogEntry', attr), {'order': index})
+
+Keys for relations only:
+
+* ``label``: label for the relations section or side box
+
+* ``showlabel``: boolean telling whether the label is displayed
+
+* ``limit``: boolean telling if the results should be limited. If so, a link to all results is displayed
+
+* ``filter``: callback taking the related result set as argument and returning it filtered
+
+.. sourcecode:: python
+
+ pv_section = uicfg.primaryview_section
+ # in `CWUser` primary view, display `created_by`
+ # relations in relations section
+ pv_section.tag_object_of(('*', 'created_by', 'CWUser'), 'relations')
+
+ # display this relation as a list, sets the label,
+ # limit the number of results and filters on comments
+ def filter_comment(rset):
+ return rset.filtered_rset(lambda x: x.e_schema == 'Comment')
+ pv_ctrl = uicfg.primaryview_display_ctrl
+ pv_ctrl.tag_object_of(('*', 'created_by', 'CWUser'),
+ {'vid': 'list', 'label': _('latest comment(s):'),
+ 'limit': True,
+ 'filter': filter_comment})
+
+.. warning:: with the ``primaryview_display_ctrl`` rtag, the subject or the
+ object of the relation is ignored for respectively ``tag_object_of`` or
+ ``tag_subject_of``. To avoid warnings during execution, they should be set to
+ ``'*'``.
+
+Rendering methods and attributes
+````````````````````````````````
+
+The basic layout of a primary view is as in the
+:ref:`primary_view_layout` section. This layout is actually drawn by
+the `render_entity` method.
+
+The methods you may want to modify while customizing a ``PrimaryView``
+are:
+
+*render_entity_title(self, entity)*
+ Renders the entity title using the ``def dc_title(self)`` method.
+
+*render_entity_metadata(self, entity)*
+ Renders the entity metadata by calling the ``metadata`` view on the
+ entity. This generic view is in cubicweb.views.baseviews.
+
+*render_entity_attributes(self, entity)*
+ Renders all the attribute of an entity with the exception of
+ attribute of type `Password` and `Bytes`. The skip_none class
+ attribute controls the display of None valued attributes.
+
+*render_entity_relations(self, entity)*
+ Renders all the relations of the entity in the main section of the page.
+
+*render_side_boxes(self, entity, boxes)*
+ Renders relations of the entity in a side box.
+
+The placement of relations in the relations section or in side boxes
+can be controlled through the :ref:`primary_view_configuration` mechanism.
+
+*content_navigation_components(self, context)*
+ This method is applicable only for entity type implementing the interface
+ `IPrevNext`. This interface is for entities which can be linked to a previous
+ and/or next entity. This method will render the navigation links between
+ entities of this type, either at the top or at the bottom of the page
+ given the context (navcontent{top|bottom}).
+
+Also, please note that by setting the following attributes in your
+subclass, you can already customize some of the rendering:
+
+*show_attr_label*
+ Renders the attribute label next to the attribute value if set to True.
+ Otherwise, does only display the attribute value.
+
+*show_rel_label*
+ Renders the relation label next to the relation value if set to True.
+ Otherwise, does only display the relation value.
+
+*skip_none*
+ Does not render an attribute value that is None if set to True.
+
+*main_related_section*
+ Renders the relations of the entity if set to True.
+
+A good practice is for you to identify the content of your entity type for which
+the default rendering does not answer your need so that you can focus on the specific
+method (from the list above) that needs to be modified. We do not advise you to
+overwrite ``render_entity`` unless you want a completely different layout.
+
+Example of customization and creation
+-------------------------------------
+
+We'll show you now an example of a ``primary`` view and how to customize it.
+
+We continue along the basic tutorial :ref:`tuto_blog`.
+
+If you want to change the way a ``BlogEntry`` is displayed, just override
+the method ``cell_call()`` of the view ``primary`` in ``BlogDemo/views.py``:
+
+.. sourcecode:: python
+
+ from cubicweb.selectors import implements
+ from cubicweb.web.views.primary improt Primaryview
+
+ class BlogEntryPrimaryView(PrimaryView):
+ __select__ = PrimaryView.__select__ & implements('BlogEntry')
+
+ def render_entity_attributes(self, entity):
+ self.w(u'<p>published on %s</p>' %
+ entity.publish_date.strftime('%Y-%m-%d'))
+ super(BlogEntryPrimaryView, self).render_entity_attributes(entity)
+
+The above source code defines a new primary view for
+``BlogEntry``. The `id` class attribute is not repeated there since it
+is inherited through the `primary.PrimaryView` class.
+
+The selector for this view chains the selector of the inherited class
+with its own specific criterion.
+
+The view method ``self.w()`` is used to output data. Here `lines
+08-09` output HTML for the publication date of the entry.
+
+.. image:: ../../../images/lax-book.09-new-view-blogentry.en.png
+ :alt: blog entries now look much nicer
+
+Let us now improve the primary view of a blog
+
+.. sourcecode:: python
+
+ from logilab.mtconverter import xml_escape
+ from cubicweb.selectors import implements, one_line_rset
+ from cubicweb.web.views.primary import Primaryview
+
+ class BlogPrimaryView(PrimaryView):
+ __regid__ = 'primary'
+ __select__ = PrimaryView.__select__ & implements('Blog')
+ rql = 'Any BE ORDERBY D DESC WHERE BE entry_of B, BE publish_date D, B eid %(b)s'
+
+ def render_entity_relations(self, entity):
+ rset = self._cw.execute(self.rql, {'b' : entity.eid})
+ for entry in rset.entities():
+ self.w(u'<p>%s</p>' % entry.view('inblogcontext'))
+
+ class BlogEntryInBlogView(EntityView):
+ __regid__ = 'inblogcontext'
+ __select__ = implements('BlogEntry')
+
+ def cell_call(self, row, col):
+ entity = self.cw_rset.get_entity(row, col)
+ self.w(u'<a href="%s" title="%s">%s</a>' %
+ entity.absolute_url(),
+ xml_escape(entity.content[:50]),
+ xml_escape(entity.description))
+
+This happens in two places. First we override the
+render_entity_relations method of a Blog's primary view. Here we want
+to display our blog entries in a custom way.
+
+At `line 10`, a simple request is made to build a result set with all
+the entities linked to the current ``Blog`` entity by the relationship
+``entry_of``. The part of the framework handling the request knows
+about the schema and infers that such entities have to be of the
+``BlogEntry`` kind and retrieves them (in the prescribed publish_date
+order).
+
+The request returns a selection of data called a result set. Result
+set objects have an .entities() method returning a generator on
+requested entities (going transparently through the `ORM` layer).
+
+At `line 13` the view 'inblogcontext' is applied to each blog entry to
+output HTML. (Note that the 'inblogcontext' view is not defined
+whatsoever in *CubicWeb*. You are absolutely free to define whole view
+families.) We juste arrange to wrap each blogentry output in a 'p'
+html element.
+
+Next, we define the 'inblogcontext' view. This is NOT a primary view,
+with its well-defined sections (title, metadata, attribtues,
+relations/boxes). All a basic view has to define is cell_call.
+
+Since views are applied to result sets which can be tables of data, we
+have to recover the entity from its (row,col)-coordinates (`line
+20`). Then we can spit some HTML.
+
+.. warning::
+
+ Be careful: all strings manipulated in *CubicWeb* are actually
+ unicode strings. While web browsers are usually tolerant to
+ incoherent encodings they are being served, we should not abuse
+ it. Hence we have to properly escape our data. The xml_escape()
+ function has to be used to safely fill (X)HTML elements from Python
+ unicode strings.
+
+Assuming we added entries to the blog titled `MyLife`, displaying it
+now allows to read its description and all its entries.
+
+.. image:: ../../../images/lax-book.10-blog-with-two-entries.en.png
+ :alt: a blog and all its entries
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/book/en/development/devweb/views/startup.rst Thu Apr 15 12:48:40 2010 +0200
@@ -0,0 +1,13 @@
+Startup views (:mod:`cubicweb.web.views.startup`)
+-------------------------------------------------
+Usual selector: no_rset or yes.
+
+Views that don't apply to a result set
+
+*index*
+ This view defines the home page of your application. It does not require
+ a result set to apply to.
+
+*schema*
+ A view dedicated to the display of the schema of the instance
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/book/en/development/devweb/views/table.rst Thu Apr 15 12:48:40 2010 +0200
@@ -0,0 +1,10 @@
+Table views (:mod:`cubicweb.web.views.table`)
+----------------------------------------------
+
+*table*
+ Creates a HTML table (`<table>`) and call the view `cell` for each cell of
+ the result set. Applicable on any result set.
+
+*cell*
+ By default redirects to the `final` view if this is a final entity or
+ `outofcontext` view otherwise
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/book/en/development/devweb/views/urlpublish.rst Thu Apr 15 12:48:40 2010 +0200
@@ -0,0 +1,7 @@
+.. -*- coding: utf-8 -*-
+
+URL Rewriting (:mod:`cubicweb.web.views.urlpublish`) and (:mod:`cubicweb.web.views.urlrewrite`)
+------------------------------------------------------------------------------------------------
+
+XXX feed me
+show how urls are mapped to selections and views and explain URLRewriting
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/book/en/development/devweb/views/views.rst Thu Apr 15 12:48:40 2010 +0200
@@ -0,0 +1,127 @@
+
+.. _Views:
+
+Principles
+----------
+
+We'll start with a description of the interface providing a basic
+understanding of the available classes and methods, then detail the
+view selection principle.
+
+A `View` is an object responsible for the rendering of data from the
+model into an end-user consummable form. They typically churn out an
+XHTML stream, but there are views concerned with email other non-html
+outputs.
+
+Basic class for views
+~~~~~~~~~~~~~~~~~~~~~
+
+Class `View` (`cubicweb.view`)
+```````````````````````````````
+
+This class is an abstraction of a view class, used as a base class for every
+renderable object such as views, templates, graphic components, etc.
+
+A `View` is instantiated to render a result set or part of a result
+set. `View` subclasses may be parametrized using the following class
+attributes:
+
+* `templatable` indicates if the view may be embedded in a main
+ template or if it has to be rendered standalone (i.e. pure XML views
+ must not be embedded in the main template of HTML pages)
+
+* if the view is not templatable, it should set the `content_type`
+ class attribute to the correct MIME type (text/xhtml being the
+ default)
+
+* the `category` attribute may be used in the interface to regroup
+ related view kinds together
+
+A view writes to its output stream thanks to its attribute `w` (the
+append method of an `UStreamIO`, except for binary views).
+
+At instantiation time, the standard `_cw` and `cw_rset` attributes are
+added and the `w` attribute will be set at rendering time.
+
+The basic interface for views is as follows (remember that the result
+set has a tabular structure with rows and columns, hence cells):
+
+* `render(**context)`, render the view by calling `call` or
+ `cell_call` depending on the context
+
+* `call(**kwargs)`, call the view for a complete result set or null
+ (the default implementation calls `cell_call()` on each cell of the
+ result set)
+
+* `cell_call(row, col, **kwargs)`, call the view for a given cell of a
+ result set (`row` and `col` being integers used to access the cell)
+
+* `url()`, returns the URL enabling us to get the view with the current
+ result set
+
+* `wview(__vid, rset, __fallback_vid=None, **kwargs)`, call the view of
+ identifier `__vid` on the given result set. It is possible to give a
+ fallback view identifier that will be used if the requested view is
+ not applicable to the result set.
+
+* `html_headers()`, returns a list of HTML headers to be set by the
+ main template
+
+* `page_title()`, returns the title to use in the HTML header `title`
+
+Other basic view classes
+````````````````````````
+Here are some of the subclasses of `View` defined in `cubicweb.common.view`
+that are more concrete as they relate to data rendering within the application:
+
+* `EntityView`, view applying to lines or cell containing an entity (e.g. an eid)
+* `StartupView`, start view that does not require a result set to apply to
+* `AnyRsetView`, view applicable to any result set
+
+Examples of views class
+```````````````````````
+
+- Using `templatable`, `content_type` and HTTP cache configuration
+
+.. sourcecode:: python
+
+ class RSSView(XMLView):
+ __regid__ = 'rss'
+ title = _('rss')
+ templatable = False
+ content_type = 'text/xml'
+ http_cache_manager = MaxAgeHTTPCacheManager
+ cache_max_age = 60*60*2 # stay in http cache for 2 hours by default
+
+
+- Using a custom selector
+
+.. sourcecode:: python
+
+ class SearchForAssociationView(EntityView):
+ """view called by the edition view when the user asks
+ to search for something to link to the edited eid
+ """
+ __regid__ = 'search-associate'
+ title = _('search for association')
+ __select__ = one_line_rset() & match_search_state('linksearch') & implements('Any')
+
+
+
+
+XML views, binaries views...
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+For views generating other formats than HTML (an image generated dynamically
+for example), and which can not simply be included in the HTML page generated
+by the main template (see above), you have to:
+
+* set the attribute `templatable` of the class to `False`
+* set, through the attribute `content_type` of the class, the MIME
+ type generated by the view to `application/octet-stream` or any
+ relevant and more specialised mime type
+
+For views dedicated to binary content creation (like dynamically generated
+images), we have to set the attribute `binary` of the class to `True` (which
+implies that `templatable == False`, so that the attribute `w` of the view could be
+replaced by a binary flow instead of unicode).
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/book/en/development/devweb/views/wdoc.rst Thu Apr 15 12:48:40 2010 +0200
@@ -0,0 +1,7 @@
+.. -*- coding: utf-8 -*-
+
+Online documentation system (:mod:`cubicweb.web.views.wdoc`)
+-------------------------------------------------------------
+
+XXX describe the on-line documentation system
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/book/en/development/devweb/views/xmlrss.rst Thu Apr 15 12:48:40 2010 +0200
@@ -0,0 +1,62 @@
+.. _XmlAndRss:
+
+XML and RSS views (:mod:`cubicweb.web.views.xmlrss`)
+----------------------------------------------------
+
+Overview
++++++++++
+
+*rss*
+ Creates a RSS/XML view and call the view `rssitem` for each entity of
+ the result set.
+
+*rssitem*
+ Create a RSS/XML view for each entity based on the results of the dublin core
+ methods of the entity (`dc_*`)
+
+
+RSS Channel Example
+++++++++++++++++++++
+
+Assuming you have several blog entries, click on the title of the
+search box in the left column. A larger search box should appear. Enter::
+
+ Any X ORDERBY D WHERE X is BlogEntry, X creation_date D
+
+and you get a list of blog entries.
+
+Click on your login at the top right corner. Chose "user preferences",
+then "boxes", then "possible views box" and check "visible = yes"
+before validating your changes.
+
+Enter the same query in the search box and you will see the same list,
+plus a box titled "possible views" in the left column. Click on
+"entityview", then "RSS".
+
+You just applied the "RSS" view to the RQL selection you requested.
+
+That's it, you have a RSS channel for your blog.
+
+Try again with::
+
+ Any X ORDERBY D WHERE X is BlogEntry, X creation_date D,
+ X entry_of B, B title "MyLife"
+
+Another RSS channel, but a bit more focused.
+
+A last one for the road::
+
+ Any C ORDERBY D WHERE C is Comment, C creation_date D LIMIT 15
+
+displayed with the RSS view, that's a channel for the last fifteen
+comments posted.
+
+[WRITE ME]
+
+* show that the RSS view can be used to display an ordered selection
+ of blog entries, thus providing a RSS channel
+
+* show that a different selection (by category) means a different channel
+
+
+
--- a/doc/book/en/development/entityclasses/data-as-objects.rst Thu Apr 15 12:47:02 2010 +0200
+++ b/doc/book/en/development/entityclasses/data-as-objects.rst Thu Apr 15 12:48:40 2010 +0200
@@ -53,7 +53,7 @@
* `set_relations(**kwargs)`, add relations to the given object. To
set a relation where this entity is the object of the relation,
- use 'reverse_'<relation> as argument name. Values may be an
+ 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).
--- a/doc/book/en/development/index.rst Thu Apr 15 12:47:02 2010 +0200
+++ b/doc/book/en/development/index.rst Thu Apr 15 12:48:40 2010 +0200
@@ -1,8 +1,8 @@
.. _Part2:
----------------------
-Part II - Development
----------------------
+-----------
+Development
+-----------
This part is about developing web applications with the *CubicWeb* framework.
@@ -19,5 +19,4 @@
devrepo/index
testing.rst
migration.rst
- webstdlib/index
profiling.rst
--- a/doc/book/en/development/testing.rst Thu Apr 15 12:47:02 2010 +0200
+++ b/doc/book/en/development/testing.rst Thu Apr 15 12:48:40 2010 +0200
@@ -3,9 +3,6 @@
Tests
=====
-.. toctree::
- :maxdepth: 1
-
Unit tests
----------
@@ -87,9 +84,12 @@
The test case itself checks that an Operation does it job of
preventing cycles amongst Keyword entities.
+You can see an example of security tests in the
+:ref:`adv_tuto_security`.
-XXX ref to advanced use case
-XXX apycot plug
+It is possible to have these tests run continuously using `apycot`_.
+
+.. _apycot: http://www.logilab.org/project/apycot
Managing connections or users
+++++++++++++++++++++++++++++
@@ -104,17 +104,31 @@
Before a self.login, one has to release the connection pool in use
with a self.commit, self.rollback or self.close.
+The `login` method returns a connection object that can be used as a
+context manager:
+
+.. sourcecode:: python
+
+ with self.login('user1') as user:
+ req = user.req
+ req.execute(...)
+
+On exit of the context manager, either a commit or rollback is issued,
+which releases the connection.
+
When one is logged in as a normal user and wants to switch back to the
-admin user, one has to use self.restore_connection().
+admin user without committing, one has to use
+self.restore_connection().
-Usually it looks like this:
+Usage with restore_connection:
.. sourcecode:: python
# execute using default admin connection
self.execute(...)
# I want to login with another user, ensure to free admin connection pool
- # (could have used rollback but not close here, we should never close defaut admin connection)
+ # (could have used rollback but not close here
+ # we should never close defaut admin connection)
self.commit()
cnx = self.login('user')
# execute using user connection
@@ -130,8 +144,6 @@
Do not use the references kept to the entities created with a
connection from another !
-XXX the new context manager ?
-
Email notifications tests
-------------------------
@@ -182,21 +194,65 @@
test. The code here has to be uncommented to be usable, without
further modification.
-XXX more to come
+The ``auto_populate`` method uses a smart algorithm to create
+pseudo-random data in the database, thus enabling the views to be
+invoked and tested.
+
+Depending on the schema, hooks and operations constraints, it is not
+always possible for the automatic auto_populate to proceed.
+It is possible of course to completely redefine auto_populate. A
+lighter solution is to give hints (fill some class attributes) about
+what entities and relations have to be skipped by the auto_populate
+mechanism. These are:
+
+* `no_auto_populate`, may contain a list of entity types to skip
+* `ignored_relations`, may contain a list of relation types to skip
+* `application_rql`, may contain a list of rql expressions that
+ auto_populate cannot guess by itself; these must yield resultsets
+ against which views may be selected.
+
+
+Test APIS
+---------
Using Pytest
````````````
-.. automodule:: logilab.common.testlib
+The `pytest` utility (shipping with `logilab-common`_, which is a
+mandatory dependency of CubicWeb) extends the Python unittest
+functionality and is the preferred way to run the CubicWeb test
+suites. Bare unittests also work the usual way.
+
+.. _logilab-common: http://www.logilab.org/project/logilab-common
+
+To use it, you may:
+
+* just launch `pytest` in your cube to execute all tests (it will
+ discover them automatically)
+* launch `pytest unittest_foo.py` to execute one test file
+* launch `pytest unittest_foo.py bar` to execute all test methods and
+ all test cases whose name contain `bar`
+
+Additionally, the `-x` option tells pytest to exit at the first error
+or failure. The `-i` option tells pytest to drop into pdb whenever an
+exception occurs in a test.
+
+When the `-x` option has been used and the run stopped on a test, it
+is possible, after having fixed the test, to relaunch pytest with the
+`-R` option to tell it to start testing again from where it previously
+failed.
+
+Using the `TestCase` base class
+```````````````````````````````
+
+The base class of CubicWebTC is logilab.common.testlib.TestCase, which
+provides a lot of convenient assertion methods.
+
.. autoclass:: logilab.common.testlib.TestCase
:members:
-XXX pytestconf.py & options (e.g --source to use a different db
-backend than sqlite)
-
CubicWebTC API
``````````````
.. autoclass:: cubicweb.devtools.testlib.CubicWebTC
:members:
-
--- a/doc/book/en/development/webstdlib/autoform.rst Thu Apr 15 12:47:02 2010 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,69 +0,0 @@
-The automatic entity form (:mod:`cubicweb.web.views.autoform`)
----------------------------------------------------------------
-
-Tags declaration
-~~~~~~~~~~~~~~~~~~~~
-
-It is possible to manage attributes/relations in the simple or multiple
-editing form thanks of the methods bellow ::
-
- uicfg.autoform_section.tag_subject_of(<relation>, tag)
- uicfg.autoform_section.tag_object_of(<relation>, tag)
- uicfg.autoform_field.tag_attribute(<attribut_def>, tag)
-
-Where ``<relation>`` is a three elements tuple ``(Subject Entity Type,
-relation_type, Object Entity Type)``. ``<attribut_def>`` is a two elements tuple
-``(Entity Type, Attribut Name)``. Wildcard ``*`` could be used in place of
-``Entity Type``
-
-Possible tags are detailled below
-
-Simple Tags
-~~~~~~~~~~~~~~~~~~~~
-
-* `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 and represented as a combobox. Each item of the
- combobox is a link to an existing entity.
-
-* `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 will be included in the
- editing form and represented as a combobox. Each item of the combobox
- is a link to an existing entity.
-
-* `inlineview`, includes the target entity's form in the editing form
- of the current entity. It allows to create the target entity in the
- same time as the current entity.
-
-* `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 necessary, it is possible to overwrite the method
-`relation_category(rtype, x='subject')` to dynamically compute
-a relation editing category.
-
-
-Advanced Tags
-~~~~~~~~~~~~~~~~~~~~
-
-Tag can also reference a custom Field crafted with the help of
-``cubicweb.web.formfields`` and ``cubicweb.web.formwidget``. In the example
-bellow, the field ``path`` of ``ExecData`` entities will be done with a standard
-file input dialogue ::
-
- from cubicweb.web import uicfg, formfields, formwidgets
-
- uicfg.autoform_field.tag_attribute(('Execdata', 'path'),
- formfields.FileField(name='path', widget=formwidgets.FileInput()))
-
-
-
-
-
-
-
--- a/doc/book/en/development/webstdlib/basetemplates.rst Thu Apr 15 12:47:02 2010 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,189 +0,0 @@
-.. -*- coding: utf-8 -*-
-
-.. _templates:
-
-Templates
-=========
-
-[WRITE ME]
-
-* talk about main templates, etc.
-
-
-
-Look at ``cubicweb/web/views/basetemplates.py`` and you will
-find the base templates used to generate HTML for your application.
-
-A page is composed as indicated on the schema below :
-
-.. image:: ../../images/lax-book.06-main-template-layout.en.png
-
-In this section we will go through a couple of the primary templates
-you must be interested in, that is to say, the HTMLPageHeader,
-the HTMLPageFooter and the TheMainTemplate.
-
-
-HTMLPageHeader
---------------
-
-Customize header
-~~~~~~~~~~~~~~~~
-
-Let's now move the search box in the header and remove the login form
-from the header. We'll show how to move it to the left column of the application.
-
-Let's say we do not want anymore the login menu to be in the header, but we
-prefer it to be in the left column just below the logo. As the left column is
-rendered by ``TheMainTemplate``, we will show how to do it in TheMainTemplate_.
-
-First, to remove the login menu, we just need to comment out the display of the
-login component such as follows : ::
-
- class MyHTMLPageHeader(HTMLPageHeader):
-
- def main_header(self, view):
- """build the top menu with authentification info and the rql box"""
- self.w(u'<table id="header"><tr>\n')
- self.w(u'<td id="firstcolumn">')
- self._cw.vreg.select_component('logo', self._cw, self.cw_rset).dispatch(w=self.w)
- self.w(u'</td>\n')
- # appliname and breadcrumbs
- self.w(u'<td id="headtext">')
- comp = self._cw.vreg.select_component('appliname', self._cw, self.cw_rset)
- if comp and comp.propval('visible'):
- comp.dispatch(w=self.w)
- comp = self._cw.vreg.select_component('breadcrumbs', self._cw, self.cw_rset, view=view)
- if comp and comp.propval('visible'):
- comp.dispatch(w=self.w, view=view)
- self.w(u'</td>')
- # logged user and help
- #self.w(u'<td>\n')
- #comp = self._cw.vreg.select_component('loggeduserlink', self._cw, self.cw_rset)
- #comp.dispatch(w=self.w)
- #self.w(u'</td><td>')
-
- self.w(u'<td>')
- helpcomp = self._cw.vreg.select_component('help', self._cw, self.cw_rset)
- if helpcomp: # may not be available if Card is not defined in the schema
- helpcomp.dispatch(w=self.w)
- self.w(u'</td>')
- # lastcolumn
- self.w(u'<td id="lastcolumn">')
- self.w(u'</td>\n')
- self.w(u'</tr></table>\n')
- self.template('logform', rset=self.cw_rset, id='popupLoginBox', klass='hidden',
- title=False, message=False)
-
-
-
-.. image:: ../../images/lax-book.06-header-no-login.en.png
-
-Let's now move the search box in the top-right header area. To do so, we will
-first create a method to get the search box display and insert it in the header
-table.
-
-::
-
- from cubicweb.web.views.basetemplates import HTMLPageHeader
- class MyHTMLPageHeader(HTMLPageHeader):
- def main_header(self, view):
- """build the top menu with authentification info and the rql box"""
- self.w(u'<table id="header"><tr>\n')
- self.w(u'<td id="firstcolumn">')
- self._cw.vreg.select_component('logo', self._cw, self.cw_rset).dispatch(w=self.w)
- self.w(u'</td>\n')
- # appliname and breadcrumbs
- self.w(u'<td id="headtext">')
- comp = self._cw.vreg.select_component('appliname', self._cw, self.cw_rset)
- if comp and comp.propval('visible'):
- comp.dispatch(w=self.w)
- comp = self._cw.vreg.select_component('breadcrumbs', self._cw, self.cw_rset, view=view)
- if comp and comp.propval('visible'):
- comp.dispatch(w=self.w, view=view)
- self.w(u'</td>')
-
- # logged user and help
- #self.w(u'<td>\n')
- #comp = self._cw.vreg.select_component('loggeduserlink', self._cw, self.cw_rset)
- #comp.dispatch(w=self.w)
- #self.w(u'</td><td>')
-
- # search box
- self.w(u'<td>')
- self.get_searchbox(view, 'left')
- self.w(u'</td>')
-
- self.w(u'<td>')
- helpcomp = self._cw.vreg.select_component('help', self._cw, self.cw_rset)
- if helpcomp: # may not be available if Card is not defined in the schema
- helpcomp.dispatch(w=self.w)
- self.w(u'</td>')
- # lastcolumn
- self.w(u'<td id="lastcolumn">')
- self.w(u'</td>\n')
- self.w(u'</tr></table>\n')
- self.template('logform', rset=self.cw_rset, id='popupLoginBox', klass='hidden',
- title=False, message=False)
-
- def get_searchbox(self, view, context):
- boxes = list(self._cw.vreg.poss_visible_objects('boxes', self._cw, self.cw_rset,
- view=view, context=context))
- if boxes:
- for box in boxes:
- if box.__regid__ == 'search_box':
- box.dispatch(w=self.w, view=view)
-
-
-
-
-HTMLPageFooter
---------------
-
-If you want to change the footer for example, look
-for HTMLPageFooter and override it in your views file as in :
-::
-
- form cubicweb.web.views.basetemplates import HTMLPageFooter
- class MyHTMLPageFooter(HTMLPageFooter):
- def call(self, **kwargs):
- self.w(u'<div class="footer">')
- self.w(u'This website has been created with <a href="http://cubicweb.org">CubicWeb</a>.')
- self.w(u'</div>')
-
-Updating a view does not require any restart of the server. By reloading
-the page you can see your new page footer.
-
-
-TheMainTemplate
----------------
-.. _TheMainTemplate:
-
-TheMainTemplate is responsible for the general layout of the entire application.
-It defines the template of ``__regid__ = main`` that is used by the instance.
-
-The default main template (`cubicweb.web.views.basetemplates.TheMainTemplate`)
-builds the page based on the following pattern:
-
-.. image:: ../../images/main_template_layout.png
-
-The rectangle containing `view.dispatch()` represents the area where the content
-view has to be displayed. The others represents sub-templates called to complete
-the page. A default implementation of those is provided in
-`cubicweb.views.basetemplates`. You can, of course, overload those sub-templates
-to implement your own customization of the HTML page.
-
-We can also control certain aspects of the main template thanks to the following
-forms parameters:
-
-* `__notemplate`, if present (whatever the value assigned), only the content view
- is returned
-* `__force_display`, if present and its value is not null, no navigation
- whatever the number of entities to display
-* `__method`, if the result set to render contains only one entity and this
- parameter is set, it refers to a method to call on the entity by passing it
- the dictionary of the forms parameters, before going the classic way (through
- step 1 and 2 described juste above)
-
-The MainTemplate is a bit complex as it tries to accomodate many
-different cases. We are now about to go through it and cutomize entirely
-our application.
--- a/doc/book/en/development/webstdlib/baseviews.rst Thu Apr 15 12:47:02 2010 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,78 +0,0 @@
-.. -*- coding: utf-8 -*-
-
-Base views (:mod:`cubicweb.web.views.baseviews`)
-------------------------------------------------
-
-*CubicWeb* provides a lot of standard views. You can find them in
-``cubicweb/web/views/``.
-
-A certain number of views are used to build the web interface, which apply
-to one or more entities. Their identifier is what distinguish them from
-each others and the main ones are:
-
-HTML views
-~~~~~~~~~~
-
-Special views
-`````````````
-
-*noresult*
- This view is the default view used when no result has been found
- (e.g. empty result set).
-
-*final*
- Display the value of a cell without trasnformation (in case of a non final
- entity, we see the eid). Applicable on any result set.
-
-*null*
- This view is the default view used when nothing needs to be rendered.
- It is always applicable and it does not return anything
-
-Entity views
-````````````
-*incontext, outofcontext*
- Those are used to display a link to an entity, depending on the
- entity having to be displayed in or out of context
- (of another entity). By default it respectively returns the
- result of `textincontext` and `textoutofcontext` wrapped in a link
- leading to the primary view of the entity.
-
-*oneline*
- This view is used when we can't tell if the entity should be considered as
- displayed in or out of context. By default it returns the result of `text`
- in a link leading to the primary view of the entity.
-
-List
-`````
-
-*list*
- This view displays a list of entities by creating a HTML list (`<ul>`)
- and call the view `listitem` for each entity of the result set.
-
-*listitem*
- This view redirects by default to the `outofcontext` view.
-
-*sameetypelist*
- This view displays a list of entities of the same type, in HTML section (`<div>`)
- and call the view `sameetypelistitem` for each entity of the result set.
-
-*sameetypelistitem*
- This view redirects by default to the `listitem` view.
-
-*csv*
- This view applies to entity groups, which are individually
- displayed using the `incontext` view. It displays each entity as a
- coma separated list. It is NOT related to the well-known text file
- format.
-
-Text entity views
-~~~~~~~~~~~~~~~~~
-*text*
- This is the simplest text view for an entity. By default it returns the
- result of the `.dc_title` method, which is cut to fit the
- `navigation.short-line-size` property if necessary.
-
-*textincontext, textoutofcontext*
- Similar to the `text` view, but called when an entity is considered out or
- in context. By default it returns respectively the result of the
- methods `.dc_title` and `.dc_long_title` of the entity.
--- a/doc/book/en/development/webstdlib/boxes.rst Thu Apr 15 12:47:02 2010 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,34 +0,0 @@
-Boxes (:mod:`cubicweb.web.views.boxes`)
----------------------------------------------------------------
-
-*sidebox*
- This view displays usually a side box of some related entities
- in a primary view.
-
-The action box
-~~~~~~~~~~~~~~~
-
-The ``add_related`` is an automatic menu in the action 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 explicitly specify them thanks to the
-`cubicweb.web.uicfg.rmode` *relation tag*:
-
-* `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 necessary, 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).
--- a/doc/book/en/development/webstdlib/breadcrumbs.rst Thu Apr 15 12:47:02 2010 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,3 +0,0 @@
-Breadcrumbs (:mod:`cubicweb.web.views.ibreadcrumbs`)
-----------------------------------------------------
-XXX feedme
\ No newline at end of file
--- a/doc/book/en/development/webstdlib/editcontroller.rst Thu Apr 15 12:47:02 2010 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,119 +0,0 @@
-.. -*- coding: utf-8 -*-
-
-The 'edit' controller (:mod:`cubicweb.web.views.editcontroller`)
-----------------------------------------------------------------
-
-Editing control
-~~~~~~~~~~~~~~~~
-
-Re-requisites: the parameters related to entities to edit are
-specified as follows ::
-
- <field name>:<entity eid>
-
-where entity eid could be a letter in case of an entity to create. We
-name those parameters as *qualified*.
-
-1. Retrieval of entities to edit by looking for the forms parameters
- starting by `eid:` and also having a parameter `__type` associated
- (also *qualified* by eid)
-
-2. For all the attributes and the relations of an entity to edit:
-
- 1. search for a parameter `edits-<relation name>` or `edito-<relation name>`
- qualified in the case of a relation where the entity is object
- 2. if found, the value returned is considered as the initial value
- for this relaiton and we then look for the new value(s) in the parameter
- <relation name> (qualified)
- 3. if the value returned is different from the initial value, an database update
- request is done
-
-3. For each entity to edit:
-
- 1. if a qualified parameter `__linkto` is specified, its value has to be
- a string (or a list of string) such as: ::
-
- <relation type>:<eids>:<target>
-
- where <target> is either `subject` or `object` and each eid could be
- separated from the others by a `_`. Target specifies if the *edited entity*
- is subject or object of the relation and each relation specified will
- be inserted.
-
- 2. if a qualified parameter `__clone_eid` is specified for an entity, the
- relations of the specified entity passed as value of this parameter are
- copied on the edited entity.
-
- 3. if a qualified parameter `__delete` is specified, its value must be
- a string or a list of string such as follows: ::
-
- <ssubjects eids>:<relation type>:<objects eids>
-
- where each eid subject or object can be seperated from the other
- by `_`. Each relation specified will be deleted.
-
- 4. if a qualified parameter `__insert` is specified, its value should
- follow the same pattern as `__delete`, but each relation specified is
- inserted.
-
-4. If the parameters `__insert` and/or `__delete` are found not qualified,
- they are interpreted as explained above (independantly from the number
- of entities edited).
-
-5. If no entity is edited but the form contains the parameters `__linkto`
- and `eid`, this one is interpreted by using the value specified for `eid`
- to designate the entity on which to add the relations.
-
-
-.. note::
-
- * If the parameter `__action_delete` is found, all the entities specified
- as to be edited will be deleted.
-
- * If the parameter`__action_cancel` is found, no action is completed.
-
- * If the parameter `__action_apply` is found, the editing is applied
- normally but the redirection is done on the form
- (see :ref:`RedirectionControl`).
-
- * The parameter `__method` is also supported as for the main template
- (XXX not very consistent, maybe __method should be dealed in the view
- controller).
-
- * If no entity is found to be edited and if there is no parameter
- `__action_delete`, `__action_cancel`, `__linkto`, `__delete` or
- `__insert`, an error is raised.
-
- * Using the parameter `__message` in the form will allow to use its value
- as a message to provide the user once the editing is completed.
-
-
-.. _RedirectionControl:
-
-Redirection control
-~~~~~~~~~~~~~~~~~~~
-Once editing is completed, there is still an issue left: where should we go
-now? If nothing is specified, the controller will do his job but it does not
-mean we will be happy with the result. We can control that by using the
-following parameters:
-
-* `__redirectpath`: path of the URL (relative to the root URL of the site,
- no form parameters
-
-* `__redirectparams`: forms parameters to add to the path
-
-* `__redirectrql`: redirection RQL request
-
-* `__redirectvid`: redirection view identifier
-
-* `__errorurl`: initial form URL, used for redirecting in case a validation
- error is raised during editing. If this one is not specified, an error page
- is displayed instead of going back to the form (which is, if necessary,
- responsible for displaying the errors)
-
-* `__form_id`: initial view form identifier, used if `__action_apply` is
- found
-
-In general we use either `__redirectpath` and `__redirectparams` or
-`__redirectrql` and `__redirectvid`.
-
--- a/doc/book/en/development/webstdlib/editforms.rst Thu Apr 15 12:47:02 2010 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,3 +0,0 @@
-Standard forms (:mod:`cubicweb.web.views.editforms`)
-----------------------------------------------------
-XXX feed me
--- a/doc/book/en/development/webstdlib/embedding.rst Thu Apr 15 12:47:02 2010 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,9 +0,0 @@
-.. -*- coding: utf-8 -*-
-
-Embedding external pages (:mod:`cubicweb.web.views.embedding`)
----------------------------------------------------------------
-
-including external content
-
-XXX feeed me
-
--- a/doc/book/en/development/webstdlib/facets.rst Thu Apr 15 12:47:02 2010 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,3 +0,0 @@
-Facets (:mod:`cubicweb.web.views.facets`)
------------------------------------------
-XXX feed me
--- a/doc/book/en/development/webstdlib/idownloadable.rst Thu Apr 15 12:47:02 2010 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,3 +0,0 @@
-The 'download' view (:mod:`cubicweb.web.views.idownloadable`)
----------------------------------------------------------------
-
--- a/doc/book/en/development/webstdlib/index.rst Thu Apr 15 12:47:02 2010 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,27 +0,0 @@
-Standard features for web interface development
-===============================================
-
-This chapter describes generic web features built as CubicWeb application objects.
-
-They are used for CubicWeb default automatic interface, but you're free to use
-them or not for you're own application.
-
-.. toctree::
- :maxdepth: 1
-
- basetemplates
- primary
- baseviews
- startup
- boxes
- table
- xmlrss
- autoform
- editforms
- editcontroller
- urlpublish
- breadcrumbs
- facets
- wdoc
- embedding
- idownloadable
\ No newline at end of file
--- a/doc/book/en/development/webstdlib/primary.rst Thu Apr 15 12:47:02 2010 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,203 +0,0 @@
-.. _primary:
-
-The Primary View
------------------
-
-(:mod:`cubicweb.web.views.primary`)
-
-By default, *CubicWeb* provides a view that fits every available
-entity type. This is the first view you might be interested in
-modifying. It is also one of the richest and most complex.
-
-It is automatically selected on a one line result set containing an
-entity.
-
-This view is supposed to render a maximum of informations about the
-entity.
-
-.. _primary_view_layout:
-
-Layout
-``````
-
-The primary view has the following layout.
-
-.. image:: ../../images/primaryview_template.png
-
-.. _primary_view_configuration:
-
-Primary view configuration
-``````````````````````````
-
-If you want to customize the primary view of an entity, overriding the primary
-view class may not be necessary. For simple adjustments (attributes or relations
-display locations and styles), a much simpler way is to use uicfg.
-
-Attributes/relations display location
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-In the primary view, there are 3 sections where attributes and
-relations can be displayed (represented in pink in the image above):
-
-* attributes
-* relations
-* sideboxes
-
-**Attributes** can only be displayed in the attributes section (default
- behavior). They can also be hidden.
-
-For instance, to hide the ``title`` attribute of the ``Blog`` entity:
-
-.. sourcecode:: python
-
- from cubicweb.web import uicfg
- uicfg.primaryview_section.tag_attribute(('Blog', 'title'), 'hidden')
-
-**Relations** can be either displayed in one of the three sections or hidden.
-
-For relations, there are two methods:
-
-* ``tag_object_of`` for modifying the primary view of the object
-* ``tag_subject_of`` for modifying the primary view of the subject
-
-These two methods take two arguments:
-
-* a triplet ``(subject, relation_name, object)``, where subject or object can be replaced with ``'*'``
-* the section name or ``hidden``
-
-.. sourcecode:: python
-
- pv_section = uicfg.primaryview_section
- # hide every relation `entry_of` in the `Blog` primary view
- pv_section.tag_object_of(('*', 'entry_of', 'Blog'), 'hidden')
-
- # display `entry_of` relations in the `relations`
- # section in the `BlogEntry` primary view
- pv_section.tag_subject_of(('BlogEntry', 'entry_of', '*'), 'relations')
-
-
-Display content
-^^^^^^^^^^^^^^^
-
-You can use ``primaryview_display_ctrl`` to customize the display of attributes
-or relations. Values of ``primaryview_display_ctrl`` are dictionaries.
-
-
-Common keys for attributes and relations are:
-
-* ``vid``: specifies the regid of the view for displaying the attribute or the relation.
-
- If ``vid`` is not specified, the default value depends on the section:
- * ``attributes`` section: 'reledit' view
- * ``relations`` section: 'autolimited' view
- * ``sideboxes`` section: 'sidebox' view
-
-* ``order``: int used to control order within a section. When not specified,
- automatically set according to order in which tags are added.
-
-.. sourcecode:: python
-
- # let us remind the schema of a blog entry
- class BlogEntry(EntityType):
- title = String(required=True, fulltextindexed=True, maxsize=256)
- publish_date = Date(default='TODAY')
- content = String(required=True, fulltextindexed=True)
- entry_of = SubjectRelation('Blog', cardinality='?*')
-
- # now, we want to show attributes
- # with an order different from that in the schema definition
- view_ctrl = uicfg.primaryview_display_ctrl
- for index, attr in enumerate('title', 'content', 'publish_date'):
- view_ctrl.tag_attribute(('BlogEntry', attr), {'order': index})
-
-Keys for relations only:
-
-* ``label``: label for the relations section or side box
-
-* ``showlabel``: boolean telling whether the label is displayed
-
-* ``limit``: boolean telling if the results should be limited. If so, a link to all results is displayed
-
-* ``filter``: callback taking the related result set as argument and returning it filtered
-
-.. sourcecode:: python
-
- pv_section = uicfg.primaryview_section
- # in `CWUser` primary view, display `created_by`
- # relations in relations section
- pv_section.tag_object_of(('*', 'created_by', 'CWUser'), 'relations')
-
- # display this relation as a list, sets the label,
- # limit the number of results and filters on comments
- def filter_comment(rset):
- return rset.filtered_rset(lambda x: x.e_schema == 'Comment')
- pv_ctrl = uicfg.primaryview_display_ctrl
- pv_ctrl.tag_object_of(('*', 'created_by', 'CWUser'),
- {'vid': 'list', 'label': _('latest comment(s):'),
- 'limit': True,
- 'filter': filter_comment})
-
-.. warning:: with the ``primaryview_display_ctrl`` rtag, the subject or the
- object of the relation is ignored for respectively ``tag_object_of`` or
- ``tag_subject_of``. To avoid warnings during execution, they should be set to
- ``'*'``.
-
-Rendering methods and attributes
-````````````````````````````````
-
-The basic layout of a primary view is as in the
-:ref:`primary_view_layout` section. This layout is actually drawn by
-the `render_entity` method.
-
-The methods you may want to modify while customizing a ``PrimaryView``
-are:
-
-*render_entity_title(self, entity)*
- Renders the entity title using the ``def dc_title(self)`` method.
-
-*render_entity_metadata(self, entity)*
- Renders the entity metadata by calling the ``metadata`` view on the
- entity. This generic view is in cubicweb.views.baseviews.
-
-*render_entity_attributes(self, entity)*
- Renders all the attribute of an entity with the exception of
- attribute of type `Password` and `Bytes`. The skip_none class
- attribute controls the display of None valued attributes.
-
-*render_entity_relations(self, entity)*
- Renders all the relations of the entity in the main section of the page.
-
-*render_side_boxes(self, entity, boxes)*
- Renders relations of the entity in a side box.
-
-The placement of relations in the relations section or in side boxes
-can be controlled through the :ref:`primary_view_configuration` mechanism.
-
-*content_navigation_components(self, context)*
- This method is applicable only for entity type implementing the interface
- `IPrevNext`. This interface is for entities which can be linked to a previous
- and/or next entity. This method will render the navigation links between
- entities of this type, either at the top or at the bottom of the page
- given the context (navcontent{top|bottom}).
-
-Also, please note that by setting the following attributes in your
-subclass, you can already customize some of the rendering:
-
-*show_attr_label*
- Renders the attribute label next to the attribute value if set to True.
- Otherwise, does only display the attribute value.
-
-*show_rel_label*
- Renders the relation label next to the relation value if set to True.
- Otherwise, does only display the relation value.
-
-*skip_none*
- Does not render an attribute value that is None if set to True.
-
-*main_related_section*
- Renders the relations of the entity if set to True.
-
-A good practice is for you to identify the content of your entity type for which
-the default rendering does not answer your need so that you can focus on the specific
-method (from the list above) that needs to be modified. We do not advise you to
-overwrite ``render_entity`` unless you want a completely different layout.
--- a/doc/book/en/development/webstdlib/startup.rst Thu Apr 15 12:47:02 2010 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,13 +0,0 @@
-Startup views (:mod:`cubicweb.web.views.startup`)
--------------------------------------------------
-Usual selector: no_rset or yes.
-
-Views that don't apply to a result set
-
-*index*
- This view defines the home page of your application. It does not require
- a result set to apply to.
-
-*schema*
- A view dedicated to the display of the schema of the instance
-
--- a/doc/book/en/development/webstdlib/table.rst Thu Apr 15 12:47:02 2010 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,10 +0,0 @@
-Table views (:mod:`cubicweb.web.views.table`)
-----------------------------------------------
-
-*table*
- Creates a HTML table (`<table>`) and call the view `cell` for each cell of
- the result set. Applicable on any result set.
-
-*cell*
- By default redirects to the `final` view if this is a final entity or
- `outofcontext` view otherwise
--- a/doc/book/en/development/webstdlib/urlpublish.rst Thu Apr 15 12:47:02 2010 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,7 +0,0 @@
-.. -*- coding: utf-8 -*-
-
-URL Rewriting (:mod:`cubicweb.web.views.urlpublish`) and (:mod:`cubicweb.web.views.urlrewrite`)
-------------------------------------------------------------------------------------------------
-
-XXX feed me
-show how urls are mapped to selections and views and explain URLRewriting
--- a/doc/book/en/development/webstdlib/wdoc.rst Thu Apr 15 12:47:02 2010 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,7 +0,0 @@
-.. -*- coding: utf-8 -*-
-
-Online documentation system (:mod:`cubicweb.web.views.wdoc`)
--------------------------------------------------------------
-
-XXX describe the on-line documentation system
-
--- a/doc/book/en/development/webstdlib/xmlrss.rst Thu Apr 15 12:47:02 2010 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,62 +0,0 @@
-.. _XmlAndRss:
-
-XML and RSS views (:mod:`cubicweb.web.views.xmlrss`)
-----------------------------------------------------
-
-Overview
-+++++++++
-
-*rss*
- Creates a RSS/XML view and call the view `rssitem` for each entity of
- the result set.
-
-*rssitem*
- Create a RSS/XML view for each entity based on the results of the dublin core
- methods of the entity (`dc_*`)
-
-
-RSS Channel Example
-++++++++++++++++++++
-
-Assuming you have several blog entries, click on the title of the
-search box in the left column. A larger search box should appear. Enter::
-
- Any X ORDERBY D WHERE X is BlogEntry, X creation_date D
-
-and you get a list of blog entries.
-
-Click on your login at the top right corner. Chose "user preferences",
-then "boxes", then "possible views box" and check "visible = yes"
-before validating your changes.
-
-Enter the same query in the search box and you will see the same list,
-plus a box titled "possible views" in the left column. Click on
-"entityview", then "RSS".
-
-You just applied the "RSS" view to the RQL selection you requested.
-
-That's it, you have a RSS channel for your blog.
-
-Try again with::
-
- Any X ORDERBY D WHERE X is BlogEntry, X creation_date D,
- X entry_of B, B title "MyLife"
-
-Another RSS channel, but a bit more focused.
-
-A last one for the road::
-
- Any C ORDERBY D WHERE C is Comment, C creation_date D LIMIT 15
-
-displayed with the RSS view, that's a channel for the last fifteen
-comments posted.
-
-[WRITE ME]
-
-* show that the RSS view can be used to display an ordered selection
- of blog entries, thus providing a RSS channel
-
-* show that a different selection (by category) means a different channel
-
-
-
Binary file doc/book/en/images/main_template.png has changed
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/book/en/images/main_template.svg Thu Apr 15 12:48:40 2010 +0200
@@ -0,0 +1,207 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="1036.6421"
+ height="845.07812"
+ id="svg2"
+ sodipodi:version="0.32"
+ inkscape:version="0.46"
+ sodipodi:docname="main_template.svg"
+ inkscape:output_extension="org.inkscape.output.svg.inkscape"
+ version="1.0"
+ inkscape:export-filename="/home/auc/cw/doc/book/en/images/main_template.png"
+ inkscape:export-xdpi="60.659016"
+ inkscape:export-ydpi="60.659016">
+ <defs
+ id="defs4">
+ <inkscape:perspective
+ sodipodi:type="inkscape:persp3d"
+ inkscape:vp_x="0 : 526.18109 : 1"
+ inkscape:vp_y="0 : 1000 : 0"
+ inkscape:vp_z="744.09448 : 526.18109 : 1"
+ inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
+ id="perspective10" />
+ </defs>
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="0.80355603"
+ inkscape:cx="510.91495"
+ inkscape:cy="422.53906"
+ inkscape:document-units="px"
+ inkscape:current-layer="layer1"
+ showgrid="false"
+ inkscape:window-width="925"
+ inkscape:window-height="1168"
+ inkscape:window-x="0"
+ inkscape:window-y="0"
+ inkscape:snap-bbox="true" />
+ <metadata
+ id="metadata7">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ inkscape:label="Calque 1"
+ inkscape:groupmode="layer"
+ id="layer1"
+ transform="translate(162.2968,90.697922)">
+ <rect
+ style="fill:#ffffff;fill-rule:evenodd;stroke:#000000;stroke-width:1.775;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="rect2439"
+ width="854.37006"
+ height="698.2019"
+ x="20.307629"
+ y="-20.575344" />
+ <rect
+ style="fill:#ffffff;fill-rule:evenodd;stroke:#000000;stroke-width:1.775;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="rect3301"
+ width="816.3457"
+ height="508.15628"
+ x="31.751091"
+ y="96.33345" />
+ <g
+ id="g3220"
+ transform="matrix(1.0035394,0,0,1,0.5745006,0)">
+ <rect
+ y="-89.447922"
+ x="-161.0468"
+ height="55.714287"
+ width="1031.1713"
+ id="rect3240"
+ style="fill:#dfdfdf;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:2.50000024;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <text
+ id="text3264"
+ y="-51.771908"
+ x="757.85767"
+ style="font-size:23.38711166px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:2.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ xml:space="preserve"><tspan
+ id="tspan3266"
+ y="-51.771908"
+ x="757.85767"
+ sodipodi:role="line">header</tspan></text>
+ </g>
+ <rect
+ style="fill:#dfdfdf;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.775;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="rect3270"
+ width="167.87744"
+ height="707.71222"
+ x="-160.02441"
+ y="-24.671618" />
+ <g
+ id="g2434"
+ transform="matrix(0.975467,0,0,1,0.6942419,-3.6587365)">
+ <rect
+ y="35.365849"
+ x="29.548275"
+ height="55.714287"
+ width="842.59979"
+ id="rect3279"
+ style="fill:#dfdfdf;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:2.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <text
+ id="text3281"
+ y="72.885193"
+ x="681.65283"
+ style="font-size:23.38711166px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:2.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ xml:space="preserve"><tspan
+ id="tspan3283"
+ y="72.885193"
+ x="681.65283"
+ sodipodi:role="line">contentheader</tspan></text>
+ </g>
+ <g
+ id="g3170"
+ transform="matrix(1.0023324,0,0,1,-2.0421673,-10.976211)">
+ <rect
+ y="698.6355"
+ x="-158.28485"
+ height="55.714287"
+ width="1032.5997"
+ id="rect3285"
+ style="fill:#dfdfdf;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:2.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <text
+ id="text3287"
+ y="736.52045"
+ x="770.28204"
+ style="font-size:23.38711166px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:2.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ xml:space="preserve"><tspan
+ id="tspan3289"
+ y="736.52045"
+ x="770.28204"
+ sodipodi:role="line">footer</tspan></text>
+ </g>
+ <g
+ id="g3211" />
+ <g
+ id="g3215"
+ transform="matrix(0.9712065,0,0,1,0.7659296,-17.074106)">
+ <rect
+ style="fill:#dfdfdf;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:2.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="rect3291"
+ width="844.62012"
+ height="55.714287"
+ x="27.850754"
+ y="629.88562" />
+ <text
+ id="text3293"
+ y="666.60339"
+ x="692.85773"
+ style="font-size:23.38711166px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:2.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ xml:space="preserve"><tspan
+ id="tspan3295"
+ y="666.60339"
+ x="692.85773"
+ sodipodi:role="line">contentfooter</tspan></text>
+ </g>
+ <text
+ xml:space="preserve"
+ style="font-size:23.38711166px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:2.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans"
+ x="-143.67273"
+ y="20.58094"
+ id="text3297"
+ sodipodi:linespacing="125%"><tspan
+ sodipodi:role="line"
+ id="tspan2432"
+ x="-143.67273"
+ y="20.58094">left column</tspan></text>
+ <text
+ transform="scale(0.9876573,1.0124969)"
+ id="text3175"
+ y="12.071429"
+ x="721.0575"
+ style="font-size:23.09845161px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:2.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ xml:space="preserve"><tspan
+ id="tspan3177"
+ y="12.071429"
+ x="721.0575"
+ sodipodi:role="line">contentcol</tspan></text>
+ <text
+ transform="scale(0.9876573,1.0124969)"
+ id="text3179"
+ y="126.27104"
+ x="701.45959"
+ style="font-size:23.09845161px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:2.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ xml:space="preserve"><tspan
+ id="tspan3181"
+ y="126.27104"
+ x="701.45959"
+ sodipodi:role="line">contentmain</tspan></text>
+ </g>
+</svg>
Binary file doc/book/en/images/primaryview_template.png has changed
--- a/doc/book/en/images/primaryview_template.svg Thu Apr 15 12:47:02 2010 +0200
+++ b/doc/book/en/images/primaryview_template.svg Thu Apr 15 12:48:40 2010 +0200
@@ -36,16 +36,16 @@
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
- inkscape:zoom="0.49497475"
- inkscape:cx="432.61573"
- inkscape:cy="370.11733"
+ inkscape:zoom="0.9357135"
+ inkscape:cx="518.32104"
+ inkscape:cy="337.0428"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="false"
- inkscape:window-width="824"
- inkscape:window-height="1094"
+ inkscape:window-width="1307"
+ inkscape:window-height="1168"
inkscape:window-x="0"
- inkscape:window-y="45" />
+ inkscape:window-y="0" />
<metadata
id="metadata7">
<rdf:RDF>
@@ -62,193 +62,173 @@
inkscape:groupmode="layer"
id="layer1"
transform="translate(162.2968,90.697922)">
+ <g
+ id="g3869"
+ transform="matrix(1,0,0,1.0373644,0,-72.039777)">
+ <rect
+ y="-15.840891"
+ x="-159.08963"
+ height="770.11017"
+ width="1033.0049"
+ id="rect3301"
+ style="fill:#ffffff;fill-rule:evenodd;stroke:#000000;stroke-width:1.90144825;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <text
+ id="text3865"
+ y="19.784882"
+ x="-150.07172"
+ style="font-size:28.67479324px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:2.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ xml:space="preserve"><tspan
+ id="tspan3867"
+ y="19.784882"
+ x="-150.07172"
+ sodipodi:role="line">contentmain</tspan></text>
+ </g>
<rect
- style="fill:#ffffff;fill-rule:evenodd;stroke:#ff0000;stroke-width:3.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
- id="rect3301"
- width="842.59973"
- height="562.81085"
- x="28.555748"
- y="53.761448" />
- <rect
- style="fill:#ffffff;fill-rule:evenodd;stroke:#000000;stroke-width:2.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ style="fill:#ffffff;fill-rule:evenodd;stroke:#000000;stroke-width:1.45654476;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="rect2383"
- width="629.62366"
- height="54.69112"
- x="54.112095"
- y="73.831123" />
+ width="772.32111"
+ height="43.888428"
+ x="-131.1837"
+ y="86.559296" />
<text
xml:space="preserve"
- style="font-size:23.38711166px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:2.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;font-family:Bitstream Vera Sans"
- x="500.19885"
- y="104.27108"
- id="text2385"><tspan
+ style="font-size:16px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:2.50000000000000000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans;font-stretch:normal;font-variant:normal;text-anchor:start;text-align:start;writing-mode:lr;line-height:125%"
+ x="-122.69418"
+ y="115.50363"
+ id="text2385"
+ sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
- x="500.19885"
- y="104.27108"
+ x="-122.69418"
+ y="115.50363"
id="tspan3163">navcontenttop</tspan></text>
<rect
- style="fill:#ffd5d5;fill-rule:evenodd;stroke:#000000;stroke-width:2.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ style="fill:#ffd5d5;fill-rule:evenodd;stroke:#000000;stroke-width:3.06523442;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="rect3167"
- width="628.2298"
- height="165.69759"
- x="54.809006"
- y="142.37053" />
+ width="770.26868"
+ height="203.16078"
+ x="-125.88269"
+ y="172.90417" />
<text
xml:space="preserve"
- style="font-size:23.38711166px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:2.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;font-family:Bitstream Vera Sans"
- x="311.65164"
- y="283.88312"
- id="text3169"><tspan
+ style="font-size:22px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:2.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans"
+ x="348.26724"
+ y="205.34305"
+ id="text3169"
+ sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
- x="311.65164"
- y="283.88312"
- id="tspan3171">view.render_entity_attributes()</tspan></text>
+ x="348.26724"
+ y="205.34305"
+ id="tspan3171">render_entity_attributes()</tspan></text>
<rect
- style="fill:#ffd5d5;fill-rule:evenodd;stroke:#000000;stroke-width:2.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ style="fill:#ffd5d5;fill-rule:evenodd;stroke:#000000;stroke-width:3.06523442;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="rect3173"
- width="627.95807"
- height="193.9873"
- x="56.373432"
- y="320.51138" />
+ width="769.93549"
+ height="237.84663"
+ x="-125.03326"
+ y="391.32156" />
<text
xml:space="preserve"
- style="font-size:23.38711166px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:2.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;font-family:Bitstream Vera Sans"
- x="320.29282"
- y="488.45456"
- id="text3175"><tspan
+ style="font-size:22px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:2.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans"
+ x="360.99954"
+ y="428.38055"
+ id="text3175"
+ sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
- x="320.29282"
- y="488.45456"
- id="tspan3177">view.render_entity_relations()</tspan></text>
+ x="360.99954"
+ y="428.38055"
+ id="tspan3177">render_entity_relations()</tspan></text>
<rect
- style="fill:#ffd5d5;fill-rule:evenodd;stroke:#000000;stroke-width:1.76090598;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ style="fill:#ffd5d5;fill-rule:evenodd;stroke:#000000;stroke-width:2.15903592;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="rect3185"
- width="145.94266"
- height="499.44452"
- x="702.43958"
- y="70.384262" />
+ width="178.93939"
+ height="612.36584"
+ x="667.10443"
+ y="84.64225" />
<text
xml:space="preserve"
- style="font-size:23.38711166px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:2.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;font-family:Bitstream Vera Sans"
- x="74.177475"
- y="-823.00977"
+ style="font-size:22px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:2.50000000000000000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans;font-stretch:normal;font-variant:normal;text-anchor:start;text-align:start;writing-mode:lr;line-height:125%"
+ x="105.32364"
+ y="-810.65997"
id="text3187"
- transform="matrix(0,1,-1,0,0,0)"><tspan
+ transform="matrix(0,1,-1,0,0,0)"
+ sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
- x="74.177475"
- y="-823.00977"
- id="tspan3189">view.render_side_boxes()</tspan></text>
+ id="tspan2408">render_side_boxes()</tspan></text>
<rect
- style="fill:#ffffff;fill-rule:evenodd;stroke:#000000;stroke-width:2.50000024;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ style="fill:#ffffff;fill-rule:evenodd;stroke:#000000;stroke-width:3.0652349;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="rect3191"
- width="629.62366"
- height="45.386246"
- x="54.112095"
- y="524.98816" />
+ width="771.97766"
+ height="55.647793"
+ x="-127.80586"
+ y="642.0293" />
<text
xml:space="preserve"
- style="font-size:23.38711166px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:2.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;font-family:Bitstream Vera Sans"
- x="456.07504"
- y="561.66559"
- id="text3181"><tspan
+ style="font-size:16px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:2.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans"
+ x="-121.22153"
+ y="674.1748"
+ id="text3181"
+ sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
- x="456.07504"
- y="561.66559"
+ x="-121.22153"
+ y="674.1748"
id="tspan3183">navcontentbottom</tspan></text>
<rect
- style="fill:#dfdfdf;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:2.50000024;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
- id="rect3240"
- width="1031.1713"
- height="55.714287"
- x="-161.0468"
- y="-89.447922" />
+ style="fill:#ffffff;fill-rule:evenodd;stroke:#000000;stroke-width:1.68198514;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="rect3881"
+ width="986.90503"
+ height="45.800392"
+ x="-128.34428"
+ y="-31.574066" />
<text
xml:space="preserve"
- style="font-size:23.38711166px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:2.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;font-family:Bitstream Vera Sans"
- x="757.85767"
- y="-51.771908"
- id="text3264"><tspan
+ style="font-size:22px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:2.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans"
+ x="355.60541"
+ y="-2.7424495"
+ id="text3883"
+ sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
- x="757.85767"
- y="-51.771908"
- id="tspan3266">header</tspan></text>
+ x="355.60541"
+ y="-2.7424495"
+ id="tspan3885">render_entity_toolbox(), render_entity_title()</tspan></text>
<rect
- style="fill:#dfdfdf;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.76090598;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
- id="rect3270"
- width="167.89117"
- height="696.74976"
- x="-160.03128"
- y="-13.70227" />
- <rect
- style="fill:#dfdfdf;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:2.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
- id="rect3279"
- width="842.59979"
- height="55.714287"
- x="28.328695"
- y="-13.41731" />
+ style="fill:#ffffff;fill-rule:evenodd;stroke:#000000;stroke-width:1.68198514;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="rect3890"
+ width="986.90503"
+ height="45.800392"
+ x="-128.87863"
+ y="19.723684" />
<text
xml:space="preserve"
- style="font-size:23.38711166px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:2.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;font-family:Bitstream Vera Sans"
- x="668.23749"
- y="25.321617"
- id="text3281"><tspan
+ style="font-size:22px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:2.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans"
+ x="565.71027"
+ y="50.135612"
+ id="text3892"
+ sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
- x="668.23749"
- y="25.321617"
- id="tspan3283">contentheader</tspan></text>
- <rect
- style="fill:#dfdfdf;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:2.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
- id="rect3285"
- width="1032.5997"
- height="55.714287"
- x="-159.50443"
- y="697.41589" />
+ x="565.71027"
+ y="50.135612"
+ id="tspan3894">render_entity_summary()</tspan></text>
<text
xml:space="preserve"
- style="font-size:23.38711166px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:2.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;font-family:Bitstream Vera Sans"
- x="770.28204"
- y="736.52045"
- id="text3287"><tspan
+ style="font-size:22px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:2.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans"
+ x="87.154541"
+ y="114.2578"
+ id="text3899"
+ sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
- x="770.28204"
- y="736.52045"
- id="tspan3289">footer</tspan></text>
- <rect
- style="fill:#dfdfdf;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:2.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
- id="rect3291"
- width="844.62012"
- height="55.714287"
- x="27.850754"
- y="627.44647" />
+ id="tspan3903"
+ x="87.154541"
+ y="114.2578">content_navigation_components('navcontenttop')</tspan></text>
<text
xml:space="preserve"
- style="font-size:23.38711166px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:2.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;font-family:Bitstream Vera Sans"
- x="680.66193"
- y="669.04254"
- id="text3293"><tspan
+ style="font-size:22px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:2.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans"
+ x="88.46772"
+ y="675.71582"
+ id="text2410"
+ sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
- x="680.66193"
- y="669.04254"
- id="tspan3295">contentfooter</tspan></text>
- <text
- xml:space="preserve"
- style="font-size:23.38711166px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:2.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;font-family:Bitstream Vera Sans"
- x="-130.25735"
- y="24.239677"
- id="text3297"><tspan
- sodipodi:role="line"
- x="-130.25735"
- y="24.239677"
- id="tspan3299">leftcolumn</tspan></text>
- <text
- xml:space="preserve"
- style="font-size:23.38711166px;font-style:normal;font-weight:normal;fill:#ff0000;fill-opacity:1;stroke:none;stroke-width:2.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;font-family:Bitstream Vera Sans"
- x="373.18518"
- y="610.24188"
- id="text3351"><tspan
- sodipodi:role="line"
- x="373.18518"
- y="610.24188"
- id="tspan3353">view.render()</tspan></text>
+ id="tspan2412"
+ x="88.46772"
+ y="675.71582">content_navigation_components('navcontenttop')</tspan></text>
</g>
</svg>
--- a/doc/book/en/index.rst Thu Apr 15 12:47:02 2010 +0200
+++ b/doc/book/en/index.rst Thu Apr 15 12:48:40 2010 +0200
@@ -44,18 +44,25 @@
=================
.. toctree::
+ :maxdepth: 2
+
+ intro/index
+ tutorials/index
+
+.. toctree::
:maxdepth: 3
- intro/index
development/index
+
+.. toctree::
+ :maxdepth: 2
+
admin/index
annexes/index
See also:
-* the complete :ref:`TOC`,
* the :ref:`genindex`,
* the :ref:`modindex`,
-* and the :ref:`search`.
.. |cubicweb| replace:: *CubicWeb*
--- a/doc/book/en/intro/book-map.rst Thu Apr 15 12:47:02 2010 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,10 +0,0 @@
-.. -*- coding: utf-8 -*-
-
-Book map
-========
-
-[XXX WRITE ME]
-
-* explain how to use this book and what chapters to read in what order depending on the
- objectives of the reader
-
--- a/doc/book/en/intro/concepts.rst Thu Apr 15 12:47:02 2010 +0200
+++ b/doc/book/en/intro/concepts.rst Thu Apr 15 12:48:40 2010 +0200
@@ -59,7 +59,7 @@
repository. For applications that support high traffic, several web (front-end)
and data (back-end) instances can be set-up to share the load.
-.. image:: ../../images/archi_globale.en.png
+.. image:: ../images/archi_globale.en.png
The command :command:`cubicweb-ctl list` also displays the list of instances
installed on your system.
--- a/doc/book/en/intro/index.rst Thu Apr 15 12:47:02 2010 +0200
+++ b/doc/book/en/intro/index.rst Thu Apr 15 12:48:40 2010 +0200
@@ -2,9 +2,9 @@
.. _Part1:
------------------------------------
-Part I - Introduction to *CubicWeb*
------------------------------------
+--------------------------
+Introduction to *CubicWeb*
+--------------------------
This first part of the book offers different reading path to
discover the *CubicWeb* framework, provides a tutorial to get a quick
@@ -15,7 +15,5 @@
:maxdepth: 2
:numbered:
- book-map
history
concepts.rst
- tutorial/index
--- a/doc/book/en/intro/tutorial/blog-in-five-minutes.rst Thu Apr 15 12:47:02 2010 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,42 +0,0 @@
-.. -*- coding: utf-8 -*-
-
-.. _BlogFiveMinutes:
-
-Get a blog running in five minutes!
------------------------------------
-
-For Debian or Ubuntu users, first install the following packages (:ref:`DebianInstallation`)::
-
- cubicweb, cubicweb-dev, cubicweb-blog
-
-For Windows or Mac OS X users, you must install cubicweb from source (see :ref:`SourceInstallation` and :ref:`WindowsInstallation`).
-
-Then create and initialize your instance::
-
- cubicweb-ctl create blog myblog
-
-And start it::
-
- cubicweb-ctl start -D myblog
-
-The -D option is the debugging mode of cubicweb, removing it will lauch the instance in the background.
-
-Permission
-~~~~~~~~~~
-
-This command assumes that you have root access to the /etc/ path. In order to initialize your instance as a `user` (from scratch), please check your current PYTHONPATH then create the ~/etc/cubicweb.d directory.
-
-Instance parameters
-~~~~~~~~~~~~~~~~~~~
-
-If the database installation failed, you'd like to change some instance parameters, for example, the database host or the user name. These informations can be edited in the `source` file located in the /etc/cubicweb.d/myblog directory.
-
-Then relaunch the database creation:
-
- cubicweb-ctl db-create myblog
-
-Other paramaters, like web server or emails parameters, can be modified in the `all-in-one.conf` file.
-
-This is it. Your blog is running. Visit http://localhost:8080 and enjoy it! This blog is fully functionnal. The next section section will present the way to develop new cubes and customizing the look of your instance.
-
-
--- a/doc/book/en/intro/tutorial/components.rst Thu Apr 15 12:47:02 2010 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,79 +0,0 @@
-.. -*- coding: utf-8 -*-
-
-.. _cubes:
-
-Cubes
------
-
-Standard library
-~~~~~~~~~~~~~~~~
-
-A library of standard cubes are available from `CubicWeb Forge`_
-Cubes provide entities and views.
-
-The available application entities in standard cubes are:
-
-* addressbook: PhoneNumber and PostalAddress
-
-* basket: Basket (like a shopping cart)
-
-* blog: Blog (a *very* basic blog)
-
-* classfolder: Folder (to organize things but grouping them in folders)
-
-* classtags: Tag (to tag anything)
-
-* comment: Comment (to attach comment threads to entities)
-
-* file: File (to allow users to upload and store binary or text files)
-
-* link: Link (to collect links to web resources)
-
-* mailinglist: MailingList (to reference a mailing-list and the URLs
- for its archives and its admin interface)
-
-* person: Person (easily mixed with addressbook)
-
-* task: Task (something to be done between start and stop date)
-
-* zone: Zone (to define places within larger places, for example a
- city in a state in a country)
-
-.. _`CubicWeb Forge`: http://www.cubicweb.org/project/
-
-Adding comments to BlogDemo
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-To import a cube in your instance just change the line in the
-``__pkginfo__.py`` file and verify that the cube you are planning
-to use is listed by the command ``cubicweb-ctl list``.
-For example::
-
- __use__ = ('comment',)
-
-will make the ``Comment`` entity available in your ``BlogDemo``
-cube.
-
-Change the schema to add a relationship between ``BlogEntry`` and
-``Comment`` and you are done. Since the comment cube defines the
-``comments`` relationship, adding the line::
-
- comments = ObjectRelation('Comment', cardinality='1*', composite='object')
-
-to the definition of a ``BlogEntry`` will be enough.
-
-Synchronize the data model
-~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-Once you modified your data model, you need to synchronize the
-database with your model. For this purpose, *CubicWeb* provides
-a very useful command ``cubicweb-ctl shell blogdemo`` which
-launches an interactive shell where you can enter migration
-commands (see :ref:`cubicweb-ctl` for more details)).
-As you added the cube named `comment`, you need to run:
-
-::
-
- add_cube('comment')
-
-You can now start your instance and comment your blog entries.
--- a/doc/book/en/intro/tutorial/conclusion.rst Thu Apr 15 12:47:02 2010 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,15 +0,0 @@
-.. -*- coding: utf-8 -*-
-
-What's next?
-------------
-
-We demonstrated how from a straight out of the box *CubicWeb* installation, you
-can build your web application based on a data model. It's all already there:
-views, templates, permissions, etc. The step forward is now for you to customize
-according to your needs.
-
-Many features are available to extend your application, for example: RSS channel
-integration (:ref:`XmlAndRss`), hooks (:ref:`hooks`), support of sources such as
-Google App Engine (:ref:`GoogleAppEngineSource`) and lots of others to discover
-through our book.
-
--- a/doc/book/en/intro/tutorial/create-cube.rst Thu Apr 15 12:47:02 2010 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,430 +0,0 @@
-.. -*- coding: utf-8 -*-
-
-
-.. _Steps:
-
-Steps for creating your cube
-----------------------------
-
-The following steps will help you to create and customize a new cube.
-
-1. :ref:`CreateYourCube`
-
-Create the directory to hold the code of your cube. The most important files that will be useful to customize your newly created cube are:
- * schema.py: contains the data model
- * views.py: contains your custom views
- * entities.py: contains XXX
-
-The detailed structure of the code directory is described in :ref:`cubelayout`.
-
-2. :ref:`DefineDataModel`
-
-Define the data model of your application.
-
-3. :ref:`ExploreYourInstance`
-
-Create, run, and explore an instance of your cube.
-
-4. :ref:`DefineViews`
-
-Customize the views of your data: how and which part of your data are showed.
-
-Note: views don't concern the look'n'feel or design of the site. For that, you should use CSS instead, and default CSS or your new cube are located in 'blog/data/'.
-
-
-5. :ref:`DefineEntities`
-
-Define your own entities to add useful functions when you manipulate your data, especially when you write view.
-
-
-.. _CreateYourCube:
-
-Create your cube
-----------------
-
-The packages ``cubicweb`` and ``cubicweb-dev`` install a command line
-tool for *CubicWeb* called ``cubicweb-ctl``. This tool provides a wide
-range of commands described in details in :ref:`cubicweb-ctl`.
-
-Once your *CubicWeb* development environment is set up, you can create
-a new cube::
-
- cubicweb-ctl newcube blog
-
-This will create in the cubes directory (``/path/to/forest/cubes`` for Mercurial
-installation, ``/usr/share/cubicweb/cubes`` for debian packages installation)
-a directory named ``blog`` reflecting the structure described in :ref:`Concepts`.
-
-
-For packages installation, you can still create new cubes in your home directory using the following configuration. Let's say you want to develop your new cubes in `~src/cubes`, then set the following environment variables:
-::
-
- CW_CUBES_PATH=~/src/cubes
- CW_MODE=user
-
-and then create your new cube using:
-::
-
- cubicweb-ctl newcube --directory=~/src/cubes blog
-
-
-
-
-
-
-.. _DefineDataModel:
-
-Define your data model
-----------------------
-
-The data model or schema is the core of your *CubicWeb* application.
-It defines the type of content your application will handle.
-
-The data model of your cube ``blog`` is defined in the file ``schema.py``:
-
-.. sourcecode:: python
-
- from yams.buildobjs import EntityType, String, SubjectRelation, Date
-
- class Blog(EntityType):
- title = String(maxsize=50, required=True)
- description = String()
-
- class BlogEntry(EntityType):
- title = String(required=True, fulltextindexed=True, maxsize=256)
- publish_date = Date(default='TODAY')
- content = String(required=True, fulltextindexed=True)
- entry_of = SubjectRelation('Blog', cardinality='?*')
-
-The first step is the import of the EntityType (generic class for entity and
-attributes that will be used in both Blog and BlogEntry entities.
-
-A Blog has a title and a description. The title is a string that is
-required and must be less than 50 characters. The
-description is a string that is not constrained.
-
-A BlogEntry has a title, a publish_date and a content. The title is a
-string that is required and must be less than 100 characters. The
-publish_date is a Date with a default value of TODAY, meaning that
-when a BlogEntry is created, its publish_date will be the current day
-unless it is modified. The content is a string that will be indexed in
-the database full-text index and has no constraint.
-
-A BlogEntry also has a relationship ``entry_of`` that links it to a
-Blog. The cardinality ``?*`` means that a BlogEntry can be part of
-zero or one Blog (``?`` means `zero or one`) and that a Blog can
-have any number of BlogEntry (``*`` means `any number including
-zero`). For completeness, remember that ``+`` means `one or more`.
-
-
-.. _ExploreYourInstance:
-
-Create and explore your instance
---------------------------------
-.. _CreateYourInstance:
-
-Create your instance
-~~~~~~~~~~~~~~~~~~~~
-
-To use this cube as an instance and create a new instance named ``blogdemo``, do::
-
- cubicweb-ctl create blog blogdemo
-
-This command will create the corresponding database and initialize it.
-
-
-.. _WelcomeToYourWebInstance:
-
-Welcome to your web instance
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-Start your instance in debug mode with the following command: ::
-
- cubicweb-ctl start -D blogdemo
-
-
-You can now access your web instance to create blogs and post messages
-by visiting the URL http://localhost:8080/.
-
-A login form will appear. By default, the instance will not allow anonymous
-users to enter the instance. To login, you need then use the admin account
-you created at the time you initialized the database with ``cubicweb-ctl
-create``.
-
-.. image:: ../../images/login-form.png
-
-
-Once authenticated, you can start playing with your instance
-and create entities.
-
-.. image:: ../../images/blog-demo-first-page.png
-
-Please notice that so far, the *CubicWeb* framework managed all aspects of
-the web application based on the schema provided at the beginning.
-
-.. _AddEntities:
-
-Add entities
-~~~~~~~~~~~~
-
-We will now add entities in our web application.
-
-Add a Blog
-**********
-
-Let us create a few of these entities. Click on the `[+]` at the left of the
-link Blog on the home page. Call this new Blog ``Tech-blog`` and type in
-``everything about technology`` as the description, then validate the form by
-clicking on ``Validate``.
-
-.. image:: ../../images/cbw-create-blog.en.png
- :alt: from to create blog
-
-Click on the logo at top left to get back to the home page, then
-follow the Blog link that will list for you all the existing Blog.
-You should be seeing a list with a single item ``Tech-blog`` you
-just created.
-
-.. image:: ../../images/cbw-list-one-blog.en.png
- :alt: displaying a list of a single blog
-
-Clicking on this item will get you to its detailed description except
-that in this case, there is not much to display besides the name and
-the phrase ``everything about technology``.
-
-Now get back to the home page by clicking on the top-left logo, then
-create a new Blog called ``MyLife`` and get back to the home page
-again to follow the Blog link for the second time. The list now
-has two items.
-
-.. image:: ../../images/cbw-list-two-blog.en.png
- :alt: displaying a list of two blogs
-
-Add a BlogEntry
-***************
-
-Get back to the home page and click on [+] at the left of the link
-BlogEntry. Call this new entry ``Hello World`` and type in some text
-before clicking on ``Validate``. You added a new blog entry without
-saying to what blog it belongs. There is a box on the left entitled
-``actions``, click on the menu item ``modify``. You are back to the form
-to edit the blog entry you just created, except that the form now has
-another section with a combobox titled ``add relation``. Chose
-``entry_of`` in this menu and a second combobox appears where you pick
-``MyLife``.
-
-You could also have, at the time you started to fill the form for a
-new entity BlogEntry, hit ``Apply`` instead of ``Validate`` and the
-combobox titled ``add relation`` would have showed up.
-
-
-.. image:: ../../images/cbw-add-relation-entryof.en.png
- :alt: editing a blog entry to add a relation to a blog
-
-Validate the changes by clicking ``Validate``. The entity BlogEntry
-that is displayed now includes a link to the entity Blog named
-``MyLife``.
-
-.. image:: ../../images/cbw-detail-one-blogentry.en.png
- :alt: displaying the detailed view of a blogentry
-
-Note that all of this was handled by the framework and that the only input
-that was provided so far is the schema. To get a graphical view of the schema,
-point your browser to the URL http://localhost:8080/schema
-
-.. image:: ../../images/cbw-schema.en.png
- :alt: graphical view of the schema (aka data-model)
-
-
-.. _DefineViews:
-
-Define your entity views
-------------------------
-
-Each entity defined in a model is associated with default views
-allowing different rendering of the data. You can redefine each of
-them according to your needs and preferences. So let's see how the
-views are defined.
-
-
-The view selection principle
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-A view is defined by a Python class which includes:
-
- - an identifier (all objects in *CubicWeb* are recorded in a
- registry and this identifier will be used as a key)
-
- - a filter to select the result sets it can be applied to
-
-A view has a set of methods complying with the `View` class interface
-(`cubicweb.common.view`).
-
-*CubicWeb* provides a lot of standard views for the type `EntityView`;
-for a complete list, read the code in directory ``cubicweb/web/views/``.
-
-A view is applied on a `result set` which contains a set of entities
-we are trying to display. *CubicWeb* uses a selector mechanism which
-computes for each available view a score: the view with the highest
-score is then used to display the given `result set`. The standard
-library of selectors is in ``cubicweb.selector``.
-
-It is possible to define multiple views for the same identifier
-and to associate selectors and filters to allow the application
-to find the most appropriate way to render the data.
-
-For example, the view named ``primary`` is the one used to display a
-single entity. We will now show you how to create a primary view for
-BlogEntry.
-
-
-Primary view customization
-~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-If you wish to modify the way a `BlogEntry` is rendered, you will have
-to subclass the `primary` view, for instance in the module ``views``
-of the cube ``cubes/blog/views.py``.
-
-The standard primary view is the most sophisticated view of all. It
-has more than a call() method. It is a template. Actually the entry
-point calls the following sequence of (redefinable) methods:
-
- * render_entity_title
-
- * render_entity_metadata
-
- * render_entity_attributes
-
- * render_entity_relations
-
- * render_side_boxes
-
-Excepted side boxes, we can see all of them already in action in the
-blog entry view. This is all described in more details in
-:ref:`primary`.
-
-We can for example add in front of the publication date a prefix
-specifying that the date we see is the publication date.
-
-To do so, please apply the following changes:
-
-.. sourcecode:: python
-
- from cubicweb.selectors import implements
- from cubicweb.web.views import primary
-
- class BlogEntryPrimaryView(primary.PrimaryView):
- __select__ = implements('BlogEntry')
-
- def render_entity_attributes(self, entity):
- self.w(u'<p>published on %s</p>' %
- entity.publish_date.strftime('%Y-%m-%d'))
- super(BlogEntryPrimaryView, self).render_entity_attributes(entity)
-
-.. note::
- When a view is modified, it is not required to restart the instance
- server. Save the Python file and reload the page in your web browser
- to view the changes.
-
-You can now see that the publication date has a prefix.
-
-.. image:: ../../images/cbw-update-primary-view.en.png
- :alt: modified primary view
-
-
-The above source code defines a new primary view for ``BlogEntry``.
-
-Since views are applied to result sets and result sets can be tables of
-data, we have to recover the entity from its (row,col)-coordinates.
-The view has a ``self.w()`` method that is used to output data, in our
-example HTML output.
-
-.. note::
- You can find more details about views and selectors in :ref:`Views`.
-
-
-.. _DefineEntities:
-
-Write entities to add logic in your data
-----------------------------------------
-
-By default, CubicWeb provides a default entity for each data type defined in the schema.
-A default entity mainly contains the attributes defined in the data model.
-
-You can redefine each entity to provide additional functions to help you write your views.
-
-.. sourcecode:: python
-
- from cubicweb.entities import AnyEntity
-
- class BlogEntry(AnyEntity):
- """customized class for BlogEntry entities"""
- __regid__ = 'BlogEntry'
- __implements__ = AnyEntity.__implements__
-
- def display_cw_logo(self):
- if 'CW' in self.title:
- return True
- else:
- return False
-
-Customizing an entity requires that your entity:
- - inherits from ``cubicweb.entities`` or any subclass
- - defines a ``__regid__`` linked to the corresponding data type of your schema
- - implements the base class by explicitly using ``__implements__``.
-
-We implemented here a function ``display_cw_logo`` which tests if the blog entry title contains 'CW'.
-This function can then be used when you customize your views. For instance, you can modify your previous ``views.py`` as follows:
-
-.. sourcecode:: python
-
- class BlogEntryPrimaryView(primary.PrimaryView):
- __select__ = implements('BlogEntry')
-
- ...
-
- def render_entity_title(self, entity):
- if entity.display_cw_logo():
- self.w(u'<image src="http://www.cubicweb.org/doc/en/_static/cubicweb.png"/>')
- super(BlogEntryPrimaryView, self).render_entity_title(entity)
-
-Then each blog entry whose title contains 'CW' is shown with the CubicWeb logo in front of it.
-
-.. _UpdatingSchemaAndSynchronisingInstance:
-
-Updating the schema and synchronising the instance
---------------------------------------------------
-
-While developping your cube, you may want to update your data model. Let's say you
-want to add a ``category`` attribute in the ``Blog`` data type. This is called a migration.
-
-The required steps are:
-1. modify the file ``schema.py``. The ``Blog`` class looks now like this:
-
-.. sourcecode:: python
-
- class Blog(EntityType):
- title = String(maxsize=50, required=True)
- description = String()
- category = String(required=True, vocabulary=(_('Professional'), _('Personal')), default='Personal')
-
-2. stop your ``blogdemo`` instance
-
-3. start the cubicweb shell for your instance by running the following command:
-
-.. sourcecode:: bash
-
- cubicweb-ctl shell blogdemo
-
-4. in the shell, execute:
-
-.. sourcecode:: python
-
- add_attribute('Blog', 'category')
-
-5. you can restart your instance, modify a blog entity and check that the new attribute
-``category`` has been added.
-
-Of course, you may also want to add relations, entity types, ... See :ref:`migration`
-for a list of all available migration commands.
-
--- a/doc/book/en/intro/tutorial/index.rst Thu Apr 15 12:47:02 2010 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,28 +0,0 @@
-.. -*- coding: utf-8 -*-
-
-.. _Tutorial:
-
-Tutorial
-========
-
-*CubicWeb* is a semantic web application framework that favors reuse and
-object-oriented design.
-
-A `cube` is a component that includes a model defining the data types and a set of
-views to display the data. A cube can be built by assembling other cubes.
-
-An `instance` is a specific installation of a cube and includes configuration
-files.
-
-
-This tutorial will show how to create a `cube` and how to use it as an
-application to run an `instance`.
-
-.. toctree::
- :maxdepth: 2
-
- blog-in-five-minutes
- create-cube
- components
- maintemplate
- conclusion
--- a/doc/book/en/intro/tutorial/maintemplate.rst Thu Apr 15 12:47:02 2010 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,131 +0,0 @@
-.. -*- coding: utf-8 -*-
-
-Templates
----------
-
-Look at ``cubicweb/web/views/basetemplates.py`` and you will
-find the base templates used to generate HTML for your application.
-
-A page is composed as indicated on the schema below:
-
-.. image:: ../../images/lax-book.06-main-template-layout.en.png
-
-In this section we will demonstrate a change in one of the main
-interesting template from the three you will look for,
-that is to say, the HTMLPageHeader, the HTMLPageFooter
-and the TheMainTemplate.
-
-
-Customize a template
-~~~~~~~~~~~~~~~~~~~~
-
-Based on the diagram below, each template can be overriden
-by your customized template. To do so, we recommand you create
-a Python module ``blog.views.templates`` to keep it organized.
-In this module you will have to import the parent class you are
-interested as follows: ::
-
- from cubicweb.web.views.basetemplates import HTMLPageHeader, \
- HTMLPageFooter, TheMainTemplate
-
-and then create your sub-class::
-
- class MyBlogHTMLPageHeader(HTMLPageHeader):
- ...
-
-Customize header
-`````````````````
-
-Let's now move the search box in the header and remove the login form from the
-header. We'll show how to move it to the left column of the user interface.
-
-Let's say we do not want anymore the login menu to be in the header
-
-First, to remove the login menu, we just need to comment out the display of the
-login graphic component such as follows:
-
-.. sourcecode:: python
-
- class MyBlogHTMLPageHeader(HTMLPageHeader):
-
- def main_header(self, view):
- """build the top menu with authentification info and the rql box"""
- self.w(u'<table id="header"><tr>\n')
- self.w(u'<td id="firstcolumn">')
- self._cw.vreg.select_component('logo', self._cw, self.cw_rset).dispatch(w=self.w)
- self.w(u'</td>\n')
- # appliname and breadcrumbs
- self.w(u'<td id="headtext">')
- comp = self._cw.vreg.select_component('appliname', self._cw, self.cw_rset)
- if comp and comp.propval('visible'):
- comp.dispatch(w=self.w)
- comp = self._cw.vreg.select_component('breadcrumbs', self._cw, self.cw_rset, view=view)
- if comp and comp.propval('visible'):
- comp.dispatch(w=self.w, view=view)
- self.w(u'</td>')
- # logged user and help
- #self.w(u'<td>\n')
- #comp = self._cw.vreg.select_component('loggeduserlink', self._cw, self.cw_rset)
- #comp.dispatch(w=self.w)
- #self.w(u'</td><td>')
-
- self.w(u'<td>')
- helpcomp = self._cw.vreg.select_component('help', self._cw, self.cw_rset)
- if helpcomp: # may not be available if Card is not defined in the schema
- helpcomp.dispatch(w=self.w)
- self.w(u'</td>')
- # lastcolumn
- self.w(u'<td id="lastcolumn">')
- self.w(u'</td>\n')
- self.w(u'</tr></table>\n')
- self.template('logform', rset=self.cw_rset, id='popupLoginBox', klass='hidden',
- title=False, message=False)
-
-
-
-.. image:: ../../images/lax-book.06-header-no-login.en.png
-
-Customize footer
-````````````````
-
-If you want to change the footer for example, look
-for HTMLPageFooter and override it in your views file as in:
-
-.. sourcecode:: python
-
- from cubicweb.web.views.basetemplates import HTMLPageFooter
-
- class MyHTMLPageFooter(HTMLPageFooter):
-
- def call(self, **kwargs):
- self.w(u'<div class="footer">')
- self.w(u'This website has been created with <a href="http://cubicweb.org">CubicWeb</a>.')
- self.w(u'</div>')
-
-Updating a view does not require any restart of the server. By reloading
-the page you can see your new page footer.
-
-
-TheMainTemplate
-```````````````
-
-.. _TheMainTemplate:
-
-The MainTemplate is a bit complex as it tries to accomodate many
-different cases. We are now about to go through it and cutomize entirely
-our application.
-
-TheMainTemplate is responsible for the general layout of the entire application.
-It defines the template of ``__regid__ = main`` that is used by the application. Is
-also defined in ``cubicweb/web/views/basetemplates.py`` another template that can
-be used based on TheMainTemplate called SimpleMainTemplate which does not have
-a top section.
-
-.. image:: ../../images/lax-book.06-simple-main-template.en.png
-
-XXX
-[WRITE ME]
-
-* customize MainTemplate and show that everything in the user
- interface can be changed
-
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/book/en/standard_theme/layout.html Thu Apr 15 12:48:40 2010 +0200
@@ -0,0 +1,13 @@
+{% extends "basic/layout.html" %}
+
+{% block header %}
+<div class="header">
+ <a href="http://www.cubicweb.org">
+ <img alt="cubicweb logo" src="{{ pathto('_static/cubicweb.png', 1) }}"/>
+ </a>
+</div>
+{% endblock %}
+
+{# puts the sidebar into "sidebar1" block i.e. before the document body #}
+{% block sidebar1 %}{{ sidebar() }}{% endblock %}
+{% block sidebar2 %}{% endblock %}
Binary file doc/book/en/standard_theme/static/contents.png has changed
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/book/en/standard_theme/static/lglb-sphinx-doc.css Thu Apr 15 12:48:40 2010 +0200
@@ -0,0 +1,376 @@
+/**
+ * Sphinx stylesheet -- Logilab theme
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ * Inspired from sphinxdoc original theme.
+ */
+
+@import url("basic.css");
+
+/* -- page layout ----------------------------------------------------------- */
+
+body {
+ font-family: 'Lucida Grande', 'Lucida Sans Unicode', 'Geneva',
+ 'Verdana', sans-serif;
+ font-size: 14px;
+ letter-spacing: -0.01em;
+ line-height: 150%;
+ text-align: center;
+ background-color: #D0D0D0;
+ color: #000000;
+ padding: 0;
+ border: 1px solid #CCBCA7;
+ min-width: 640px;
+ margin: 0px 30px 0px 30px;
+}
+
+div.document {
+ background-color: #FFFFFF;
+ text-align: left;
+ background-image: url(contents.png);
+ background-repeat: repeat-x;
+}
+
+div.bodywrapper {
+ margin: 0 0 0 230px;
+ border-left: 1px solid #CCBCA7;
+}
+
+div.body {
+ margin: 0;
+ padding: 0.5em 20px 20px 20px;
+}
+
+div.header {
+ margin: 0;
+ padding: 5px 5px 25px 5px;
+ background-color: #FFFFFF;
+ text-align: left;
+ line-height: 80%;
+ }
+
+div.related {
+ font-size: 1em;
+}
+
+div.related ul {
+ background-image: url(navigation.png);
+ height: 2em;
+ border-top: 1px solid #CCBCA7;
+ border-bottom: 1px solid #CCBCA7;
+}
+
+div.related ul li {
+ margin: 0;
+ padding: 0;
+ height: 2em;
+ float: left;
+}
+
+div.related ul li.right {
+ float: right;
+ margin-right: 5px;
+}
+
+div.related ul li a {
+ margin: 0;
+ padding: 0 5px 0 5px;
+ line-height: 1.75em;
+}
+
+div.sphinxsidebarwrapper {
+ padding: 0;
+}
+
+div.sphinxsidebar {
+ margin: 0;
+ padding: 5px 10px 5px 10px;
+ width: 210px;
+ float: left;
+ font-size: 1em;
+ text-align: left;
+}
+
+div.sphinxsidebar h3, div.sphinxsidebar h4 {
+ margin: 1em 0 0.5em 0;
+ font-size: 1em;
+ padding: 0.1em 0 0.1em 0.5em;
+ color: white;
+ border: 1px solid #CCBCA7;
+ background-color: #909090;
+}
+
+div.sphinxsidebar h3 a {
+ color: white;
+}
+
+div.sphinxsidebar ul {
+ padding-left: 1.5em;
+ margin-top: 7px;
+ padding: 0;
+ line-height: 130%;
+ font-weight: bold;
+}
+
+div.sphinxsidebar ul ul {
+ margin-left: 20px;
+ font-weight: normal;
+}
+
+div.sphinxsidebar li {
+ margin: 0;
+}
+
+div.sphinxsidebar input {
+ border: 1px solid #CCBCA7;
+ font-family: sans-serif;
+ font-size: 1em;
+}
+
+div.footer {
+ background-color: #FFFFFF;
+ color: #707070;
+ padding: 3px 8px 3px 0;
+ clear: both;
+ font-size: 0.8em;
+ text-align: right;
+}
+
+div.footer a {
+ color: #707070;
+ text-decoration: underline;
+}
+
+/* -- body styles ----------------------------------------------------------- */
+
+p {
+ margin: 0.8em 0 0 0;
+}
+
+ul, ol {
+ margin: 0;
+}
+
+li {
+ margin: 0.2em 0 0 0;
+}
+
+a {
+ color: #B45300;
+ text-decoration: none;
+}
+
+a:hover {
+ color: #4BACFF;
+}
+
+div.body a {
+ text-decoration: underline;
+}
+
+h1 {
+ margin: 0;
+ padding: 0.7em 0 0.3em 0;
+ font-size: 1.5em;
+ border-bottom: 3px solid #CC8B00;
+ color: #404040;
+}
+
+h2 {
+ margin: 1.3em 0 0.2em 0;
+ font-size: 1.35em;
+ padding: 0;
+ color: #303030;
+}
+
+h3 {
+ margin: 1em 0 -0.3em 0;
+ font-size: 1.2em;
+ color: #202020;
+}
+
+div.body h1 a {
+ color: #404040!important;
+}
+
+div.body h2 a {
+ color: #303030!important;
+}
+
+div.body h3 a {
+ color: #202020!important;
+}
+
+div.body h4 a, div.body h5 a, div.body h6 a {
+ color: #000000!important;
+}
+
+h1 a.anchor, h2 a.anchor, h3 a.anchor, h4 a.anchor, h5 a.anchor, h6 a.anchor {
+ display: none;
+ margin: 0 0 0 0.3em;
+ padding: 0 0.2em 0 0.2em;
+ color: #AAA!important;
+}
+
+h1:hover a.anchor, h2:hover a.anchor, h3:hover a.anchor, h4:hover a.anchor,
+h5:hover a.anchor, h6:hover a.anchor {
+ display: inline;
+}
+
+h1 a.anchor:hover, h2 a.anchor:hover, h3 a.anchor:hover, h4 a.anchor:hover,
+h5 a.anchor:hover, h6 a.anchor:hover {
+ color: #777;
+ background-color: #EEE;
+}
+
+a.headerlink {
+ color: #C60F0F!important;
+ font-size: 1em;
+ margin-left: 6px;
+ padding: 0 4px 0 4px;
+ text-decoration: none!important;
+}
+
+a.headerlink:hover {
+ background-color: #C0C0C0;
+ color: #FFFFFF!important;
+}
+
+cite, code, tt {
+ font-family: 'Consolas', 'Deja Vu Sans Mono',
+ 'Bitstream Vera Sans Mono', monospace;
+ font-size: 0.95em;
+ letter-spacing: 0.01em;
+}
+
+tt {
+ background-color: #F0F0F0;
+ border-bottom: 1px solid #D0D0D0;
+}
+
+tt.descname, tt.descclassname, tt.xref {
+ background-color: #F0F0F0;
+ font-weight: normal;
+ font-size: 1em;
+ border: 1px solid #D0D0D0;
+ border: 0;
+}
+
+hr {
+ border: 1px solid #CC8B00;
+ margin: 2em;
+}
+
+a tt {
+ border: 0;
+ color: #B45300;
+}
+
+a:hover tt {
+ color: #4BACFF;
+}
+
+pre {
+ font-family: 'Consolas', 'Deja Vu Sans Mono',
+ 'Bitstream Vera Sans Mono', monospace;
+ font-size: 0.95em;
+ letter-spacing: 0.015em;
+ line-height: 120%;
+ padding: 0.5em;
+ border: 1px solid #CCBCA7;
+ background-color: #F0F0F0;
+}
+
+pre a {
+ color: inherit;
+ text-decoration: underline;
+}
+
+td.linenos pre {
+ padding: 0.5em 0;
+}
+
+div.quotebar {
+ background-color: #F8F8F8;
+ max-width: 250px;
+ float: right;
+ padding: 2px 7px;
+ border: 1px solid #C0C0C0;
+}
+
+div.topic {
+ background-color: #F8F8F8;
+}
+
+table {
+ border-collapse: collapse;
+ margin: 0.8em -0.5em 0em -0.5em;
+}
+
+table td, table th {
+ padding: 0.2em 0.5em 0.2em 0.5em;
+}
+
+div.admonition, div.warning {
+ font-size: 0.9em;
+ margin: 1em 0 1em 0;
+ padding: 0;
+}
+
+div.admonition {
+ border: 1px solid #86989B;
+ background-color: #EBEBFF;
+}
+
+div.warning {
+ border: 1px solid #940000;
+ background-color: #FFEBEB;
+}
+
+div.admonition p, div.warning p {
+ margin: 0.5em 1em 0.5em 1em;
+ padding: 0;
+}
+
+div.admonition pre, div.warning pre {
+ margin: 0.4em 1em 0.4em 1em;
+}
+
+div.admonition p.admonition-title,
+div.warning p.admonition-title {
+ margin: 0;
+ padding: 0.1em 0 0.1em 0.5em;
+ color: #FFFFFF;
+ font-weight: bold;
+}
+
+div.admonition p.admonition-title {
+ border-bottom: 1px solid #86989B;
+ background-color: #8C88B5;
+}
+
+div.warning p.admonition-title {
+ background-color: #CF0000;
+ border-bottom: 1px solid #940000;
+}
+
+div.admonition ul, div.admonition ol,
+div.warning ul, div.warning ol {
+ margin: 0.1em 0.5em 0.5em 3em;
+ padding: 0;
+}
+
+div.versioninfo {
+ margin: 1em 0 0 0;
+ border: 1px solid #C0C0C0;
+ background-color: #DDEAF0;
+ padding: 8px;
+ line-height: 1.3em;
+ font-size: 0.9em;
+}
+
+/* TOC trees */
+
+li.toctree-l1 {
+ margin-top: 0.4em;
+ }
\ No newline at end of file
Binary file doc/book/en/standard_theme/static/logilab_logo.png has changed
Binary file doc/book/en/standard_theme/static/navigation.png has changed
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/book/en/standard_theme/theme.conf Thu Apr 15 12:48:40 2010 +0200
@@ -0,0 +1,4 @@
+[theme]
+inherit = basic
+stylesheet = lglb-sphinx-doc.css
+pygments_style = friendly
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/book/en/tutorials/advanced/index.rst Thu Apr 15 12:48:40 2010 +0200
@@ -0,0 +1,586 @@
+.. _advanced_tutorial:
+
+Building a photo gallery with CubicWeb
+======================================
+
+Desired features
+----------------
+
+* basically a photo gallery
+
+* photo stored onto the fs and displayed dynamically through a web interface
+
+* navigation through folder (album), tags, geographical zone, people on the
+ picture... using facets
+
+* advanced security (eg not everyone can see everything). More on this later.
+
+
+Cube creation and schema definition
+-----------------------------------
+
+.. _adv_tuto_create_new_cube:
+
+Step 1: creating a new cube for my web site
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+One note about my development environment: I wanted to use packaged
+version of CubicWeb and cubes while keeping my cube in my user
+directory, let's say `~src/cubes`. I achieve this by setting the
+following environment variables::
+
+ CW_CUBES_PATH=~/src/cubes
+ CW_MODE=user
+
+I can now create the cube which will hold custom code for this web
+site using::
+
+ c-c newcube --directory=~/src/cubes sytweb
+
+
+.. _adv_tuto_assemble_cubes:
+
+Step 2: pick building blocks into existing cubes
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Almost everything I want represent in my web-site is somewhat already modelized in
+some cube that I'll extend for my need. So I'll pick the following cubes:
+
+* `folder`, containing `Folder` entity type, which will be used as
+ both 'album' and a way to map file system folders. Entities are
+ added to a given folder using the `filed_under` relation.
+
+* `file`, containing `File` and `Image` entity types, gallery view,
+ and a file system import utility.
+
+* `zone`, containing the `Zone` entity type for hierarchical geographical
+ zones. Entities (including sub-zones) are added to a given zone using the
+ `situated_in` relation.
+
+* `person`, containing the `Person` entity type plus some basic views.
+
+* `comment`, providing a full commenting system allowing one to comment entity types
+ supporting the `comments` relation by adding a `Comment` entity.
+
+* `tag`, providing a full tagging system as a easy and powerful way to classify
+ entities supporting the `tags` relation by linking the to `Tag` entities. This
+ will allows navigation into a large number of picture.
+
+Ok, now I'll tell my cube requires all this by editing cubes/sytweb/__pkginfo__.py:
+
+ .. sourcecode:: python
+
+ __depends_cubes__ = {'file': '>= 1.2.0',
+ 'folder': '>= 1.1.0',
+ 'person': '>= 1.2.0',
+ 'comment': '>= 1.2.0',
+ 'tag': '>= 1.2.0',
+ 'zone': None,
+ }
+ __depends__ = {'cubicweb': '>= 3.5.10',
+ }
+ for key,value in __depends_cubes__.items():
+ __depends__['cubicweb-'+key] = value
+ __use__ = tuple(__depends_cubes__)
+
+Notice that you can express minimal version of the cube that should be used,
+`None` meaning whatever version available.
+
+Step 3: glue everything together in my cube's schema
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+.. sourcecode:: python
+
+ from yams.buildobjs import RelationDefinition
+
+ class comments(RelationDefinition):
+ subject = 'Comment'
+ object = ('File', 'Image')
+ cardinality = '1*'
+ composite = 'object'
+
+ class tags(RelationDefinition):
+ subject = 'Tag'
+ object = ('File', 'Image')
+
+ class filed_under(RelationDefinition):
+ subject = ('File', 'Image')
+ object = 'Folder'
+
+ class situated_in(RelationDefinition):
+ subject = 'Image'
+ object = 'Zone'
+
+ class displayed_on(RelationDefinition):
+ subject = 'Person'
+ object = 'Image'
+
+
+This schema:
+
+* allows to comment and tag on `File` and `Image` entity types by adding the
+ `comments` and `tags` relations. This should be all we've to do for this
+ feature since the related cubes provide 'pluggable section' which are
+ automatically displayed on the primary view of entity types supporting the
+ relation.
+
+* adds a `situated_in` relation definition so that image entities can be
+ geolocalized.
+
+* add a new relation `displayed_on` relation telling who can be seen on a
+ picture.
+
+This schema will probably have to evolve as time goes (for security handling at
+least), but since the possibility to make schema evolving is one of CubicWeb
+feature (and goal), we won't worry and see that later when needed.
+
+
+Step 4: creating the instance
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Now that I've a schema, I want to create an instance so I can start To
+create an instance using this new 'sytweb' cube, I run::
+
+ c-c create sytweb sytweb_instance
+
+hint : if you get an error while the database is initialized, you can
+avoid having to reanswer to questions by runing ::
+
+ c-c db-create sytweb_instance
+
+This will use your already configured instance and start directly from the create
+database step, thus skipping questions asked by the 'create' command.
+
+Once the instance and database are fully initialized, run ::
+
+ c-c start sytweb_instance
+
+to start the instance, check you can connect on it, etc...
+
+
+Security, testing and migration
+-------------------------------
+
+This post will cover various topics:
+
+* configuring security
+* migrating existing instance
+* writing some unit tests
+
+Here is the ``read`` security model I want:
+
+* folders, files, images and comments should have one of the following visibility:
+ - ``public``, everyone can see it
+ - ``authenticated``, only authenticated users can see it
+ - ``restricted``, only a subset of authenticated users can see it
+* managers (e.g. me) can see everything
+* only authenticated user can see people
+* everyone can see classifier entities, eg tag and zone
+
+Also, unless explicity specified, visibility of an image should be the same as
+its parent folder, as well as visibility of a comment should be the same as the
+commented entity. If there is no parent entity, the default visibility is
+``authenticated``.
+
+Regarding write security, that's much easier:
+* anonymous can't write anything
+* authenticated users can only add comment
+* managers will add the remaining stuff
+
+Now, let's implement that!
+
+Proper security in CubicWeb is done at the schema level, so you don't have to
+bother with it in views: users will only see what they can see automatically.
+
+.. _adv_tuto_security:
+
+Step 1: configuring security into the schema
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+In schema, you can grant access according to groups, or to some RQL expressions:
+users get access it the expression return some results. To implements the read
+security defined earlier, groups are not enough, we'll need RQL expression. Here
+is the idea:
+
+* add a `visibility` attribute on folder, image and comment, which may be one of
+ the value explained above
+
+* add a `may_be_read_by` relation from folder, image and comment to users,
+ which will define who can see the entity
+
+* security propagation will be done in hook.
+
+So the first thing to do is to modify my cube'schema.py to define those
+relations:
+
+.. sourcecode:: python
+
+ from yams.constraints import StaticVocabularyConstraint
+
+ class visibility(RelationDefinition):
+ subject = ('Folder', 'File', 'Image', 'Comment')
+ object = 'String'
+ constraints = [StaticVocabularyConstraint(('public', 'authenticated',
+ 'restricted', 'parent'))]
+ default = 'parent'
+ cardinality = '11' # required
+
+ class may_be_read_by(RelationDefinition):
+ subject = ('Folder', 'File', 'Image', 'Comment',)
+ object = 'CWUser'
+
+We can note the following points:
+
+* we've added a new `visibility` attribute to folder, file, image and comment
+ using a `RelationDefinition`
+
+* `cardinality = '11'` means this attribute is required. This is usually hidden
+ under the `required` argument given to the `String` constructor, but we can
+ rely on this here (same thing for StaticVocabularyConstraint, which is usually
+ hidden by the `vocabulary` argument)
+
+* the `parent` possible value will be used for visibility propagation
+
+Now, we should be able to define security rules in the schema, based on these new
+attribute and relation. Here is the code to add to *schema.py*:
+
+.. sourcecode:: python
+
+ from cubicweb.schema import ERQLExpression
+
+ VISIBILITY_PERMISSIONS = {
+ 'read': ('managers',
+ ERQLExpression('X visibility "public"'),
+ ERQLExpression('X may_be_read_by U')),
+ 'add': ('managers',),
+ 'update': ('managers', 'owners',),
+ 'delete': ('managers', 'owners'),
+ }
+ AUTH_ONLY_PERMISSIONS = {
+ 'read': ('managers', 'users'),
+ 'add': ('managers',),
+ 'update': ('managers', 'owners',),
+ 'delete': ('managers', 'owners'),
+ }
+ CLASSIFIERS_PERMISSIONS = {
+ 'read': ('managers', 'users', 'guests'),
+ 'add': ('managers',),
+ 'update': ('managers', 'owners',),
+ 'delete': ('managers', 'owners'),
+ }
+
+ from cubes.folder.schema import Folder
+ from cubes.file.schema import File, Image
+ from cubes.comment.schema import Comment
+ from cubes.person.schema import Person
+ from cubes.zone.schema import Zone
+ from cubes.tag.schema import Tag
+
+ Folder.__permissions__ = VISIBILITY_PERMISSIONS
+ File.__permissions__ = VISIBILITY_PERMISSIONS
+ Image.__permissions__ = VISIBILITY_PERMISSIONS
+ Comment.__permissions__ = VISIBILITY_PERMISSIONS.copy()
+ Comment.__permissions__['add'] = ('managers', 'users',)
+ Person.__permissions__ = AUTH_ONLY_PERMISSIONS
+ Zone.__permissions__ = CLASSIFIERS_PERMISSIONS
+ Tag.__permissions__ = CLASSIFIERS_PERMISSIONS
+
+What's important in there:
+
+* `VISIBILITY_PERMISSIONS` provides read access to managers group, if
+ `visibility` attribute's value is 'public', or if user (designed by the 'U'
+ variable in the expression) is linked to the entity (the 'X' variable) through
+ the `may_read` permission
+
+* we modify permissions of the entity types we use by importing them and
+ modifying their `__permissions__` attribute
+
+* notice the `.copy()`: we only want to modify 'add' permission for `Comment`,
+ not for all entity types using `VISIBILITY_PERMISSIONS`!
+
+* the remaining part of the security model is done using regular groups:
+
+ - `users` is the group to which all authenticated users will belong
+ - `guests` is the group of anonymous users
+
+
+.. _adv_tuto_security_propagation:
+
+Step 2: security propagation in hooks
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+To fullfill the requirements, we have to implement::
+
+ Also, unless explicity specified, visibility of an image should be the same as
+ its parent folder, as well as visibility of a comment should be the same as the
+ commented entity.
+
+This kind of `active` rule will be done using CubicWeb's hook
+system. Hooks are triggered on database event such as addition of new
+entity or relation.
+
+The trick part of the requirement is in *unless explicitly specified*, notably
+because when the entity addition hook is added, we don't know yet its 'parent'
+entity (eg folder of an image, image commented by a comment). To handle such things,
+CubicWeb provides `Operation`, which allow to schedule things to do at commit time.
+
+In our case we will:
+
+* on entity creation, schedule an operation that will set default visibility
+
+* when a "parent" relation is added, propagate parent's visibility unless the
+ child already has a visibility set
+
+Here is the code in cube's *hooks.py*:
+
+.. sourcecode:: python
+
+ from cubicweb.selectors import implements
+ from cubicweb.server import hook
+
+ class SetVisibilityOp(hook.Operation):
+ def precommit_event(self):
+ for eid in self.session.transaction_data.pop('pending_visibility'):
+ entity = self.session.entity_from_eid(eid)
+ if entity.visibility == 'parent':
+ entity.set_attributes(visibility=u'authenticated')
+
+ class SetVisibilityHook(hook.Hook):
+ __regid__ = 'sytweb.setvisibility'
+ __select__ = hook.Hook.__select__ & implements('Folder', 'File', 'Image', 'Comment')
+ events = ('after_add_entity',)
+ def __call__(self):
+ hook.set_operation(self._cw, 'pending_visibility', self.entity.eid,
+ SetVisibilityOp)
+
+ class SetParentVisibilityHook(hook.Hook):
+ __regid__ = 'sytweb.setparentvisibility'
+ __select__ = hook.Hook.__select__ & hook.match_rtype('filed_under', 'comments')
+ events = ('after_add_relation',)
+
+ def __call__(self):
+ parent = self._cw.entity_from_eid(self.eidto)
+ child = self._cw.entity_from_eid(self.eidfrom)
+ if child.visibility == 'parent':
+ child.set_attributes(visibility=parent.visibility)
+
+Notice:
+
+* hooks are application objects, hence have selectors that should match entity or
+ relation types to which the hook applies. To match a relation type, we use the
+ hook specific `match_rtype` selector.
+
+* usage of `set_operation`: instead of adding an operation for each added entity,
+ set_operation allows to create a single one and to store entity's eids to be
+ processed in session's transaction data. This is a good pratice to avoid heavy
+ operations manipulation cost when creating a lot of entities in the same
+ transaction.
+
+* the `precommit_event` method of the operation will be called at transaction's
+ commit time.
+
+* in a hook, `self._cw` is the repository session, not a web request as usually
+ in views
+
+* according to hook's event, you have access to different attributes on the hook
+ instance. Here:
+
+ - `self.entity` is the newly added entity on 'after_add_entity' events
+
+ - `self.eidfrom` / `self.eidto` are the eid of the subject / object entity on
+ 'after_add_relatiohn' events (you may also get the relation type using
+ `self.rtype`)
+
+The `parent` visibility value is used to tell "propagate using parent security"
+because we want that attribute to be required, so we can't use None value else
+we'll get an error before we get any chance to propagate...
+
+Now, we also want to propagate the `may_be_read_by` relation. Fortunately,
+CubicWeb provides some base hook classes for such things, so we only have to add
+the following code to *hooks.py*:
+
+.. sourcecode:: python
+
+ # relations where the "parent" entity is the subject
+ S_RELS = set()
+ # relations where the "parent" entity is the object
+ O_RELS = set(('filed_under', 'comments',))
+
+ class AddEntitySecurityPropagationHook(hook.PropagateSubjectRelationHook):
+ """propagate permissions when new entity are added"""
+ __regid__ = 'sytweb.addentity_security_propagation'
+ __select__ = (hook.PropagateSubjectRelationHook.__select__
+ & hook.match_rtype_sets(S_RELS, O_RELS))
+ main_rtype = 'may_be_read_by'
+ subject_relations = S_RELS
+ object_relations = O_RELS
+
+ class AddPermissionSecurityPropagationHook(hook.PropagateSubjectRelationAddHook):
+ """propagate permissions when new entity are added"""
+ __regid__ = 'sytweb.addperm_security_propagation'
+ __select__ = (hook.PropagateSubjectRelationAddHook.__select__
+ & hook.match_rtype('may_be_read_by',))
+ subject_relations = S_RELS
+ object_relations = O_RELS
+
+ class DelPermissionSecurityPropagationHook(hook.PropagateSubjectRelationDelHook):
+ __regid__ = 'sytweb.delperm_security_propagation'
+ __select__ = (hook.PropagateSubjectRelationDelHook.__select__
+ & hook.match_rtype('may_be_read_by',))
+ subject_relations = S_RELS
+ object_relations = O_RELS
+
+* the `AddEntitySecurityPropagationHook` will propagate the relation
+ when `filed_under` or `comments` relations are added
+
+ - the `S_RELS` and `O_RELS` set as well as the `match_rtype_sets` selector are
+ used here so that if my cube is used by another one, it'll be able to
+ configure security propagation by simply adding relation to one of the two
+ sets.
+
+* the two others will propagate permissions changes on parent entities to
+ children entities
+
+
+.. _adv_tuto_tesing_security:
+
+Step 3: testing our security
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Security is tricky. Writing some tests for it is a very good idea. You should
+even write them first, as Test Driven Development recommends!
+
+Here is a small test case that will check the basis of our security
+model, in *test/unittest_sytweb.py*:
+
+.. sourcecode:: python
+
+ from cubicweb.devtools.testlib import CubicWebTC
+ from cubicweb import Binary
+
+ class SecurityTC(CubicWebTC):
+
+ def test_visibility_propagation(self):
+ # create a user for later security checks
+ toto = self.create_user('toto')
+ # init some data using the default manager connection
+ req = self.request()
+ folder = req.create_entity('Folder',
+ name=u'restricted',
+ visibility=u'restricted')
+ photo1 = req.create_entity('Image',
+ data_name=u'photo1.jpg',
+ data=Binary('xxx'),
+ filed_under=folder)
+ self.commit()
+ photo1.clear_all_caches() # good practice, avoid request cache effects
+ # visibility propagation
+ self.assertEquals(photo1.visibility, 'restricted')
+ # unless explicitly specified
+ photo2 = req.create_entity('Image',
+ data_name=u'photo2.jpg',
+ data=Binary('xxx'),
+ visibility=u'public',
+ filed_under=folder)
+ self.commit()
+ self.assertEquals(photo2.visibility, 'public')
+ # test security
+ self.login('toto')
+ req = self.request()
+ self.assertEquals(len(req.execute('Image X')), 1) # only the public one
+ self.assertEquals(len(req.execute('Folder X')), 0) # restricted...
+ # may_be_read_by propagation
+ self.restore_connection()
+ folder.set_relations(may_be_read_by=toto)
+ self.commit()
+ photo1.clear_all_caches()
+ self.failUnless(photo1.may_be_read_by)
+ # test security with permissions
+ self.login('toto')
+ req = self.request()
+ self.assertEquals(len(req.execute('Image X')), 2) # now toto has access to photo2
+ self.assertEquals(len(req.execute('Folder X')), 1) # and to restricted folder
+
+ if __name__ == '__main__':
+ from logilab.common.testlib import unittest_main
+ unittest_main()
+
+It's not complete, but show most things you'll want to do in tests: adding some
+content, creating users and connecting as them in the test, etc...
+
+To run it type: ::
+
+ [syt@scorpius test]$ pytest unittest_sytweb.py
+ ======================== unittest_sytweb.py ========================
+ -> creating tables [....................]
+ -> inserting default user and default groups.
+ -> storing the schema in the database [....................]
+ -> database for instance data initialized.
+ .
+ ----------------------------------------------------------------------
+ Ran 1 test in 22.547s
+
+ OK
+
+
+The first execution is taking time, since it creates a sqlite database for the
+test instance. The second one will be much quicker: ::
+
+ [syt@scorpius test]$ pytest unittest_sytweb.py
+ ======================== unittest_sytweb.py ========================
+ .
+ ----------------------------------------------------------------------
+ Ran 1 test in 2.662s
+
+ OK
+
+If you do some changes in your schema, you'll have to force regeneration of that
+database. You do that by removing the tmpdb files before running the test: ::
+
+ [syt@scorpius test]$ rm tmpdb*
+
+
+.. Note::
+ pytest is a very convenient utilities to control test execution, from the `logilab-common`_
+ package
+
+.. _`logilab-common`: http://www.logilab.org/project/logilab-common
+
+.. _adv_tuto_migration_script:
+
+Step 4: writing the migration script and migrating the instance
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Prior to those changes, Iv'e created an instance, feeded it with some data, so I
+don't want to create a new one, but to migrate the existing one. Let's see how to
+do that.
+
+Migration commands should be put in the cube's *migration* directory, in a
+file named file:`<X.Y.Z>_Any.py` ('Any' being there mostly for historical reason).
+
+Here I'll create a *migration/0.2.0_Any.py* file containing the following
+instructions:
+
+.. sourcecode:: python
+
+ add_relation_type('may_be_read_by')
+ add_relation_type('visibility')
+ sync_schema_props_perms()
+
+Then I update the version number in cube's *__pkginfo__.py* to 0.2.0. And
+that's it! Those instructions will:
+
+* update the instance's schema by adding our two new relations and update the
+ underlying database tables accordingly (the two first instructions)
+
+* update schema's permissions definition (the later instruction)
+
+
+To migrate my instance I simply type::
+
+ [syt@scorpius ~]$ cubicweb-ctl upgrade sytweb
+
+I'll then be asked some questions to do the migration step by step. You should say
+YES when it asks if a backup of your database should be done, so you can get back
+to initial state if anything goes wrong...
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/book/en/tutorials/base/blog-in-five-minutes.rst Thu Apr 15 12:48:40 2010 +0200
@@ -0,0 +1,42 @@
+.. -*- coding: utf-8 -*-
+
+.. _BlogFiveMinutes:
+
+Get a blog running in five minutes!
+-----------------------------------
+
+For Debian or Ubuntu users, first install the following packages (:ref:`DebianInstallation`)::
+
+ cubicweb, cubicweb-dev, cubicweb-blog
+
+For Windows or Mac OS X users, you must install cubicweb from source (see :ref:`SourceInstallation` and :ref:`WindowsInstallation`).
+
+Then create and initialize your instance::
+
+ cubicweb-ctl create blog myblog
+
+And start it::
+
+ cubicweb-ctl start -D myblog
+
+The -D option is the debugging mode of cubicweb, removing it will lauch the instance in the background.
+
+Permission
+~~~~~~~~~~
+
+This command assumes that you have root access to the /etc/ path. In order to initialize your instance as a `user` (from scratch), please check your current PYTHONPATH then create the ~/etc/cubicweb.d directory.
+
+Instance parameters
+~~~~~~~~~~~~~~~~~~~
+
+If the database installation failed, you'd like to change some instance parameters, for example, the database host or the user name. These informations can be edited in the `source` file located in the /etc/cubicweb.d/myblog directory.
+
+Then relaunch the database creation:
+
+ cubicweb-ctl db-create myblog
+
+Other paramaters, like web server or emails parameters, can be modified in the `all-in-one.conf` file.
+
+This is it. Your blog is running. Visit http://localhost:8080 and enjoy it! This blog is fully functionnal. The next section section will present the way to develop new cubes and customizing the look of your instance.
+
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/book/en/tutorials/base/components.rst Thu Apr 15 12:48:40 2010 +0200
@@ -0,0 +1,79 @@
+.. -*- coding: utf-8 -*-
+
+.. _cubes:
+
+Cubes
+-----
+
+Standard library
+~~~~~~~~~~~~~~~~
+
+A library of standard cubes are available from `CubicWeb Forge`_
+Cubes provide entities and views.
+
+The available application entities in standard cubes are:
+
+* addressbook: PhoneNumber and PostalAddress
+
+* basket: Basket (like a shopping cart)
+
+* blog: Blog (a *very* basic blog)
+
+* classfolder: Folder (to organize things but grouping them in folders)
+
+* classtags: Tag (to tag anything)
+
+* comment: Comment (to attach comment threads to entities)
+
+* file: File (to allow users to upload and store binary or text files)
+
+* link: Link (to collect links to web resources)
+
+* mailinglist: MailingList (to reference a mailing-list and the URLs
+ for its archives and its admin interface)
+
+* person: Person (easily mixed with addressbook)
+
+* task: Task (something to be done between start and stop date)
+
+* zone: Zone (to define places within larger places, for example a
+ city in a state in a country)
+
+.. _`CubicWeb Forge`: http://www.cubicweb.org/project/
+
+Adding comments to BlogDemo
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+To import a cube in your instance just change the line in the
+``__pkginfo__.py`` file and verify that the cube you are planning
+to use is listed by the command ``cubicweb-ctl list``.
+For example::
+
+ __use__ = ('comment',)
+
+will make the ``Comment`` entity available in your ``BlogDemo``
+cube.
+
+Change the schema to add a relationship between ``BlogEntry`` and
+``Comment`` and you are done. Since the comment cube defines the
+``comments`` relationship, adding the line::
+
+ comments = ObjectRelation('Comment', cardinality='1*', composite='object')
+
+to the definition of a ``BlogEntry`` will be enough.
+
+Synchronize the data model
+~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Once you modified your data model, you need to synchronize the
+database with your model. For this purpose, *CubicWeb* provides
+a very useful command ``cubicweb-ctl shell blogdemo`` which
+launches an interactive shell where you can enter migration
+commands (see :ref:`cubicweb-ctl` for more details)).
+As you added the cube named `comment`, you need to run:
+
+::
+
+ add_cube('comment')
+
+You can now start your instance and comment your blog entries.
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/book/en/tutorials/base/conclusion.rst Thu Apr 15 12:48:40 2010 +0200
@@ -0,0 +1,15 @@
+.. -*- coding: utf-8 -*-
+
+What's next?
+------------
+
+We demonstrated how from a straight out of the box *CubicWeb* installation, you
+can build your web application based on a data model. It's all already there:
+views, templates, permissions, etc. The step forward is now for you to customize
+according to your needs.
+
+Many features are available to extend your application, for example: RSS channel
+integration (:ref:`XmlAndRss`), hooks (:ref:`hooks`), support of sources such as
+Google App Engine (:ref:`GoogleAppEngineSource`) and lots of others to discover
+through our book.
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/book/en/tutorials/base/create-cube.rst Thu Apr 15 12:48:40 2010 +0200
@@ -0,0 +1,431 @@
+.. -*- coding: utf-8 -*-
+
+.. _Steps:
+
+Steps for creating your cube
+----------------------------
+
+The following steps will help you to create and customize a new cube.
+
+1. :ref:`CreateYourCube`
+
+Create the directory to hold the code of your cube. The most important
+files that will be useful to customize your newly created cube are:
+
+ * schema.py: contains the data model
+ * views.py: contains your custom views
+ * entities.py: contains XXX
+
+The detailed structure of the code directory is described in :ref:`cubelayout`.
+
+2. :ref:`DefineDataModel`
+
+Define the data model of your application.
+
+3. :ref:`ExploreYourInstance`
+
+Create, run, and explore an instance of your cube.
+
+4. :ref:`DefineViews`
+
+Customize the views of your data: how and which part of your data are showed.
+
+Note: views don't concern the look'n'feel or design of the site. For that, you should use CSS instead, and default CSS or your new cube are located in 'blog/data/'.
+
+
+5. :ref:`DefineEntities`
+
+Define your own entities to add useful functions when you manipulate your data, especially when you write view.
+
+
+.. _CreateYourCube:
+
+Create your cube
+----------------
+
+The packages ``cubicweb`` and ``cubicweb-dev`` install a command line
+tool for *CubicWeb* called ``cubicweb-ctl``. This tool provides a wide
+range of commands described in details in :ref:`cubicweb-ctl`.
+
+Once your *CubicWeb* development environment is set up, you can create
+a new cube::
+
+ cubicweb-ctl newcube blog
+
+This will create in the cubes directory (``/path/to/forest/cubes`` for Mercurial
+installation, ``/usr/share/cubicweb/cubes`` for debian packages installation)
+a directory named ``blog`` reflecting the structure described in :ref:`Concepts`.
+
+
+For packages installation, you can still create new cubes in your home directory using the following configuration. Let's say you want to develop your new cubes in `~src/cubes`, then set the following environment variables:
+::
+
+ CW_CUBES_PATH=~/src/cubes
+ CW_MODE=user
+
+and then create your new cube using:
+::
+
+ cubicweb-ctl newcube --directory=~/src/cubes blog
+
+
+
+
+
+
+.. _DefineDataModel:
+
+Define your data model
+----------------------
+
+The data model or schema is the core of your *CubicWeb* application.
+It defines the type of content your application will handle.
+
+The data model of your cube ``blog`` is defined in the file ``schema.py``:
+
+.. sourcecode:: python
+
+ from yams.buildobjs import EntityType, String, SubjectRelation, Date
+
+ class Blog(EntityType):
+ title = String(maxsize=50, required=True)
+ description = String()
+
+ class BlogEntry(EntityType):
+ title = String(required=True, fulltextindexed=True, maxsize=256)
+ publish_date = Date(default='TODAY')
+ content = String(required=True, fulltextindexed=True)
+ entry_of = SubjectRelation('Blog', cardinality='?*')
+
+The first step is the import of the EntityType (generic class for entity and
+attributes that will be used in both Blog and BlogEntry entities.
+
+A Blog has a title and a description. The title is a string that is
+required and must be less than 50 characters. The
+description is a string that is not constrained.
+
+A BlogEntry has a title, a publish_date and a content. The title is a
+string that is required and must be less than 100 characters. The
+publish_date is a Date with a default value of TODAY, meaning that
+when a BlogEntry is created, its publish_date will be the current day
+unless it is modified. The content is a string that will be indexed in
+the database full-text index and has no constraint.
+
+A BlogEntry also has a relationship ``entry_of`` that links it to a
+Blog. The cardinality ``?*`` means that a BlogEntry can be part of
+zero or one Blog (``?`` means `zero or one`) and that a Blog can
+have any number of BlogEntry (``*`` means `any number including
+zero`). For completeness, remember that ``+`` means `one or more`.
+
+
+.. _ExploreYourInstance:
+
+Create and explore your instance
+--------------------------------
+.. _CreateYourInstance:
+
+Create your instance
+~~~~~~~~~~~~~~~~~~~~
+
+To use this cube as an instance and create a new instance named ``blogdemo``, do::
+
+ cubicweb-ctl create blog blogdemo
+
+This command will create the corresponding database and initialize it.
+
+
+.. _WelcomeToYourWebInstance:
+
+Welcome to your web instance
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Start your instance in debug mode with the following command: ::
+
+ cubicweb-ctl start -D blogdemo
+
+
+You can now access your web instance to create blogs and post messages
+by visiting the URL http://localhost:8080/.
+
+A login form will appear. By default, the instance will not allow anonymous
+users to enter the instance. To login, you need then use the admin account
+you created at the time you initialized the database with ``cubicweb-ctl
+create``.
+
+.. image:: ../../images/login-form.png
+
+
+Once authenticated, you can start playing with your instance
+and create entities.
+
+.. image:: ../../images/blog-demo-first-page.png
+
+Please notice that so far, the *CubicWeb* framework managed all aspects of
+the web application based on the schema provided at the beginning.
+
+.. _AddEntities:
+
+Add entities
+~~~~~~~~~~~~
+
+We will now add entities in our web application.
+
+Add a Blog
+**********
+
+Let us create a few of these entities. Click on the `[+]` at the left of the
+link Blog on the home page. Call this new Blog ``Tech-blog`` and type in
+``everything about technology`` as the description, then validate the form by
+clicking on ``Validate``.
+
+.. image:: ../../images/cbw-create-blog.en.png
+ :alt: from to create blog
+
+Click on the logo at top left to get back to the home page, then
+follow the Blog link that will list for you all the existing Blog.
+You should be seeing a list with a single item ``Tech-blog`` you
+just created.
+
+.. image:: ../../images/cbw-list-one-blog.en.png
+ :alt: displaying a list of a single blog
+
+Clicking on this item will get you to its detailed description except
+that in this case, there is not much to display besides the name and
+the phrase ``everything about technology``.
+
+Now get back to the home page by clicking on the top-left logo, then
+create a new Blog called ``MyLife`` and get back to the home page
+again to follow the Blog link for the second time. The list now
+has two items.
+
+.. image:: ../../images/cbw-list-two-blog.en.png
+ :alt: displaying a list of two blogs
+
+Add a BlogEntry
+***************
+
+Get back to the home page and click on [+] at the left of the link
+BlogEntry. Call this new entry ``Hello World`` and type in some text
+before clicking on ``Validate``. You added a new blog entry without
+saying to what blog it belongs. There is a box on the left entitled
+``actions``, click on the menu item ``modify``. You are back to the form
+to edit the blog entry you just created, except that the form now has
+another section with a combobox titled ``add relation``. Chose
+``entry_of`` in this menu and a second combobox appears where you pick
+``MyLife``.
+
+You could also have, at the time you started to fill the form for a
+new entity BlogEntry, hit ``Apply`` instead of ``Validate`` and the
+combobox titled ``add relation`` would have showed up.
+
+
+.. image:: ../../images/cbw-add-relation-entryof.en.png
+ :alt: editing a blog entry to add a relation to a blog
+
+Validate the changes by clicking ``Validate``. The entity BlogEntry
+that is displayed now includes a link to the entity Blog named
+``MyLife``.
+
+.. image:: ../../images/cbw-detail-one-blogentry.en.png
+ :alt: displaying the detailed view of a blogentry
+
+Note that all of this was handled by the framework and that the only input
+that was provided so far is the schema. To get a graphical view of the schema,
+point your browser to the URL http://localhost:8080/schema
+
+.. image:: ../../images/cbw-schema.en.png
+ :alt: graphical view of the schema (aka data-model)
+
+
+.. _DefineViews:
+
+Define your entity views
+------------------------
+
+Each entity defined in a model is associated with default views
+allowing different renderings of the data. You can redefine each of
+them according to your needs and preferences. So let's see how the
+views are defined.
+
+
+The view selection principle
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+A view is defined by a Python class which includes:
+
+ - an identifier (all objects in *CubicWeb* are recorded in a
+ registry and this identifier will be used as a key)
+
+ - a filter to select the result sets it can be applied to
+
+A view has a set of methods complying with the `View` class interface
+(`cubicweb.common.view`).
+
+*CubicWeb* provides a lot of standard views for the type `EntityView`;
+for a complete list, read the code in directory ``cubicweb/web/views/``.
+
+A view is applied on a `result set` which contains a set of entities
+we are trying to display. *CubicWeb* uses a selector mechanism which
+computes for each available view a score: the view with the highest
+score is then used to display the given `result set`. The standard
+library of selectors is in ``cubicweb.selector``.
+
+It is possible to define multiple views for the same identifier
+and to associate selectors and filters to allow the application
+to find the most appropriate way to render the data.
+
+For example, the view named ``primary`` is the one used to display a
+single entity. We will now show you how to create a primary view for
+BlogEntry.
+
+
+Primary view customization
+~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+If you wish to modify the way a `BlogEntry` is rendered, you will have
+to subclass the `primary` view, for instance in the module ``views``
+of the cube ``cubes/blog/views.py``.
+
+The standard primary view is the most sophisticated view of all. It
+has more than a call() method. It is a template. Actually the entry
+point calls the following sequence of (redefinable) methods:
+
+ * render_entity_title
+
+ * render_entity_metadata
+
+ * render_entity_attributes
+
+ * render_entity_relations
+
+ * render_side_boxes
+
+Excepted side boxes, we can see all of them already in action in the
+blog entry view. This is all described in more details in
+:ref:`primary`.
+
+We can for example add in front of the publication date a prefix
+specifying that the date we see is the publication date.
+
+To do so, please apply the following changes:
+
+.. sourcecode:: python
+
+ from cubicweb.selectors import implements
+ from cubicweb.web.views import primary
+
+ class BlogEntryPrimaryView(primary.PrimaryView):
+ __select__ = implements('BlogEntry')
+
+ def render_entity_attributes(self, entity):
+ self.w(u'<p>published on %s</p>' %
+ entity.publish_date.strftime('%Y-%m-%d'))
+ super(BlogEntryPrimaryView, self).render_entity_attributes(entity)
+
+.. note::
+ When a view is modified, it is not required to restart the instance
+ server. Save the Python file and reload the page in your web browser
+ to view the changes.
+
+You can now see that the publication date has a prefix.
+
+.. image:: ../../images/cbw-update-primary-view.en.png
+ :alt: modified primary view
+
+
+The above source code defines a new primary view for ``BlogEntry``.
+
+Since views are applied to result sets and result sets can be tables of
+data, we have to recover the entity from its (row,col)-coordinates.
+The view has a ``self.w()`` method that is used to output data, in our
+example HTML output.
+
+.. note::
+ You can find more details about views and selectors in :ref:`Views`.
+
+
+.. _DefineEntities:
+
+Write entities to add logic in your data
+----------------------------------------
+
+By default, CubicWeb provides a default entity for each data type defined in the schema.
+A default entity mainly contains the attributes defined in the data model.
+
+You can redefine each entity to provide additional functions to help you write your views.
+
+.. sourcecode:: python
+
+ from cubicweb.entities import AnyEntity
+
+ class BlogEntry(AnyEntity):
+ """customized class for BlogEntry entities"""
+ __regid__ = 'BlogEntry'
+ __implements__ = AnyEntity.__implements__
+
+ def display_cw_logo(self):
+ if 'CW' in self.title:
+ return True
+ else:
+ return False
+
+Customizing an entity requires that your entity:
+ - inherits from ``cubicweb.entities`` or any subclass
+ - defines a ``__regid__`` linked to the corresponding data type of your schema
+ - implements the base class by explicitly using ``__implements__``.
+
+We implemented here a function ``display_cw_logo`` which tests if the blog entry title contains 'CW'.
+This function can then be used when you customize your views. For instance, you can modify your previous ``views.py`` as follows:
+
+.. sourcecode:: python
+
+ class BlogEntryPrimaryView(primary.PrimaryView):
+ __select__ = implements('BlogEntry')
+
+ ...
+
+ def render_entity_title(self, entity):
+ if entity.display_cw_logo():
+ self.w(u'<image src="http://www.cubicweb.org/doc/en/_static/cubicweb.png"/>')
+ super(BlogEntryPrimaryView, self).render_entity_title(entity)
+
+Then each blog entry whose title contains 'CW' is shown with the CubicWeb logo in front of it.
+
+.. _UpdatingSchemaAndSynchronisingInstance:
+
+Updating the schema and synchronising the instance
+--------------------------------------------------
+
+While developping your cube, you may want to update your data model. Let's say you
+want to add a ``category`` attribute in the ``Blog`` data type. This is called a migration.
+
+The required steps are:
+1. modify the file ``schema.py``. The ``Blog`` class looks now like this:
+
+.. sourcecode:: python
+
+ class Blog(EntityType):
+ title = String(maxsize=50, required=True)
+ description = String()
+ category = String(required=True, vocabulary=(_('Professional'), _('Personal')), default='Personal')
+
+2. stop your ``blogdemo`` instance
+
+3. start the cubicweb shell for your instance by running the following command:
+
+.. sourcecode:: bash
+
+ cubicweb-ctl shell blogdemo
+
+4. in the shell, execute:
+
+.. sourcecode:: python
+
+ add_attribute('Blog', 'category')
+
+5. you can restart your instance, modify a blog entity and check that the new attribute
+``category`` has been added.
+
+Of course, you may also want to add relations, entity types, ... See :ref:`migration`
+for a list of all available migration commands.
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/book/en/tutorials/base/index.rst Thu Apr 15 12:48:40 2010 +0200
@@ -0,0 +1,30 @@
+.. -*- coding: utf-8 -*-
+
+.. _Tutorial:
+
+.. _tuto_blog:
+
+Building a simple blog
+======================
+
+*CubicWeb* is a semantic web application framework that favors reuse and
+object-oriented design.
+
+A `cube` is a component that includes a model defining the data types and a set of
+views to display the data. A cube can be built by assembling other cubes.
+
+An `instance` is a specific installation of a cube and includes configuration
+files.
+
+
+This tutorial will show how to create a `cube` and how to use it as an
+application to run an `instance`.
+
+.. toctree::
+ :maxdepth: 2
+
+ blog-in-five-minutes
+ create-cube
+ components
+ maintemplate
+ conclusion
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/book/en/tutorials/base/maintemplate.rst Thu Apr 15 12:48:40 2010 +0200
@@ -0,0 +1,131 @@
+.. -*- coding: utf-8 -*-
+
+Templates
+---------
+
+Look at ``cubicweb/web/views/basetemplates.py`` and you will
+find the base templates used to generate HTML for your application.
+
+A page is composed as indicated on the schema below:
+
+.. image:: ../../images/lax-book.06-main-template-layout.en.png
+
+In this section we will demonstrate a change in one of the main
+interesting template from the three you will look for,
+that is to say, the HTMLPageHeader, the HTMLPageFooter
+and the TheMainTemplate.
+
+
+Customize a template
+~~~~~~~~~~~~~~~~~~~~
+
+Based on the diagram below, each template can be overriden
+by your customized template. To do so, we recommand you create
+a Python module ``blog.views.templates`` to keep it organized.
+In this module you will have to import the parent class you are
+interested as follows: ::
+
+ from cubicweb.web.views.basetemplates import HTMLPageHeader, \
+ HTMLPageFooter, TheMainTemplate
+
+and then create your sub-class::
+
+ class MyBlogHTMLPageHeader(HTMLPageHeader):
+ ...
+
+Customize header
+`````````````````
+
+Let's now move the search box in the header and remove the login form from the
+header. We'll show how to move it to the left column of the user interface.
+
+Let's say we do not want anymore the login menu to be in the header
+
+First, to remove the login menu, we just need to comment out the display of the
+login graphic component such as follows:
+
+.. sourcecode:: python
+
+ class MyBlogHTMLPageHeader(HTMLPageHeader):
+
+ def main_header(self, view):
+ """build the top menu with authentification info and the rql box"""
+ self.w(u'<table id="header"><tr>\n')
+ self.w(u'<td id="firstcolumn">')
+ self._cw.vreg.select_component('logo', self._cw, self.cw_rset).dispatch(w=self.w)
+ self.w(u'</td>\n')
+ # appliname and breadcrumbs
+ self.w(u'<td id="headtext">')
+ comp = self._cw.vreg.select_component('appliname', self._cw, self.cw_rset)
+ if comp and comp.propval('visible'):
+ comp.dispatch(w=self.w)
+ comp = self._cw.vreg.select_component('breadcrumbs', self._cw, self.cw_rset, view=view)
+ if comp and comp.propval('visible'):
+ comp.dispatch(w=self.w, view=view)
+ self.w(u'</td>')
+ # logged user and help
+ #self.w(u'<td>\n')
+ #comp = self._cw.vreg.select_component('loggeduserlink', self._cw, self.cw_rset)
+ #comp.dispatch(w=self.w)
+ #self.w(u'</td><td>')
+
+ self.w(u'<td>')
+ helpcomp = self._cw.vreg.select_component('help', self._cw, self.cw_rset)
+ if helpcomp: # may not be available if Card is not defined in the schema
+ helpcomp.dispatch(w=self.w)
+ self.w(u'</td>')
+ # lastcolumn
+ self.w(u'<td id="lastcolumn">')
+ self.w(u'</td>\n')
+ self.w(u'</tr></table>\n')
+ self.template('logform', rset=self.cw_rset, id='popupLoginBox', klass='hidden',
+ title=False, message=False)
+
+
+
+.. image:: ../../images/lax-book.06-header-no-login.en.png
+
+Customize footer
+````````````````
+
+If you want to change the footer for example, look
+for HTMLPageFooter and override it in your views file as in:
+
+.. sourcecode:: python
+
+ from cubicweb.web.views.basetemplates import HTMLPageFooter
+
+ class MyHTMLPageFooter(HTMLPageFooter):
+
+ def call(self, **kwargs):
+ self.w(u'<div class="footer">')
+ self.w(u'This website has been created with <a href="http://cubicweb.org">CubicWeb</a>.')
+ self.w(u'</div>')
+
+Updating a view does not require any restart of the server. By reloading
+the page you can see your new page footer.
+
+
+TheMainTemplate
+```````````````
+
+.. _TheMainTemplate:
+
+The MainTemplate is a bit complex as it tries to accomodate many
+different cases. We are now about to go through it and cutomize entirely
+our application.
+
+TheMainTemplate is responsible for the general layout of the entire application.
+It defines the template of ``__regid__ = main`` that is used by the application. Is
+also defined in ``cubicweb/web/views/basetemplates.py`` another template that can
+be used based on TheMainTemplate called SimpleMainTemplate which does not have
+a top section.
+
+.. image:: ../../images/lax-book.06-simple-main-template.en.png
+
+XXX
+[WRITE ME]
+
+* customize MainTemplate and show that everything in the user
+ interface can be changed
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/book/en/tutorials/index.rst Thu Apr 15 12:48:40 2010 +0200
@@ -0,0 +1,19 @@
+.. _Tutorials:
+
+---------
+Tutorials
+---------
+
+We present two tutorials of different levels. The blog building
+tutorial introduces one smoothly to the basic concepts.
+
+Then there is a photo gallery construction tutorial which highlights
+more advanced concepts such as unit tests, security settings,
+migration scripts.
+
+.. toctree::
+ :maxdepth: 1
+ :numbered:
+
+ base/index
+ advanced/index
--- a/etwist/server.py Thu Apr 15 12:47:02 2010 +0200
+++ b/etwist/server.py Thu Apr 15 12:48:40 2010 +0200
@@ -194,7 +194,7 @@
"""Render a page from the root resource"""
# reload modified files in debug mode
if self.debugmode:
- self.appli.vreg.register_objects(self.config.vregistry_path())
+ self.appli.vreg.reload_if_needed()
if self.config['profile']: # default profiler don't trace threads
return self.render_request(request)
else:
--- a/vregistry.py Thu Apr 15 12:47:02 2010 +0200
+++ b/vregistry.py Thu Apr 15 12:48:40 2010 +0200
@@ -31,8 +31,7 @@
from logilab.common.logging_ext import set_log_methods
from cubicweb import CW_SOFTWARE_ROOT
-from cubicweb import (RegistryNotFound, ObjectNotFound, NoSelectableObject,
- RegistryOutOfDate)
+from cubicweb import RegistryNotFound, ObjectNotFound, NoSelectableObject
from cubicweb.appobject import AppObject
def _toload_info(path, extrapath, _toload=None):
@@ -246,8 +245,18 @@
def __init__(self, config):
super(VRegistry, self).__init__()
self.config = config
+ # need to clean sys.path this to avoid import confusion pb (i.e. having
+ # the same module loaded as 'cubicweb.web.views' subpackage and as
+ # views' or 'web.views' subpackage. This is mainly for testing purpose,
+ # we should'nt need this in production environment
+ for webdir in (join(dirname(realpath(__file__)), 'web'),
+ join(dirname(__file__), 'web')):
+ if webdir in sys.path:
+ sys.path.remove(webdir)
+ if CW_SOFTWARE_ROOT in sys.path:
+ sys.path.remove(CW_SOFTWARE_ROOT)
- def reset(self, path=None, force_reload=None):
+ def reset(self):
# don't use self.clear, we want to keep existing subdictionaries
for subdict in self.itervalues():
subdict.clear()
@@ -392,60 +401,61 @@
self._loadedmods = {}
return filemods
- def register_objects(self, path, force_reload, extrapath=None):
- # need to clean sys.path this to avoid import confusion pb (i.e.
- # having the same module loaded as 'cubicweb.web.views' subpackage and
- # as views' or 'web.views' subpackage
- # this is mainly for testing purpose, we should'nt need this in
- # production environment
- for webdir in (join(dirname(realpath(__file__)), 'web'),
- join(dirname(__file__), 'web')):
- if webdir in sys.path:
- sys.path.remove(webdir)
- if CW_SOFTWARE_ROOT in sys.path:
- sys.path.remove(CW_SOFTWARE_ROOT)
+ def register_objects(self, path, force_reload=False, extrapath=None):
# load views from each directory in the instance's path
filemods = self.init_registration(path, extrapath)
- change = False
for filepath, modname in filemods:
- if self.load_file(filepath, modname, force_reload):
- change = True
- if change:
- self.initialization_completed()
- return change
+ self.load_file(filepath, modname, force_reload)
+ self.initialization_completed()
def initialization_completed(self):
for regname, reg in self.iteritems():
reg.initialization_completed()
+ def _mdate(self, filepath):
+ try:
+ return stat(filepath)[-2]
+ except OSError:
+ # this typically happens on emacs backup files (.#foo.py)
+ self.warning('Unable to load %s. It is likely to be a backup file',
+ filepath)
+ return None
+
+ def is_reload_needed(self, path):
+ """return True if something module changed and the registry should be
+ reloaded
+ """
+ lastmodifs = self._lastmodifs
+ for fileordir in path:
+ if isdir(fileordir) and exists(join(fileordir, '__init__.py')):
+ if self.is_reload_needed([join(fileordir, fname)
+ for fname in listdir(fileordir)]):
+ return True
+ elif fileordir[-3:] == '.py':
+ mdate = self._mdate(fileordir)
+ if mdate is None:
+ continue # backup file, see _mdate implementation
+ if fileordir not in lastmodifs or lastmodifs[fileordir] < mdate:
+ self.info('File %s changed since last visit', fileordir)
+ return True
+ return False
+
def load_file(self, filepath, modname, force_reload=False):
"""load app objects from a python file"""
from logilab.common.modutils import load_module_from_name
if modname in self._loadedmods:
return
self._loadedmods[modname] = {}
- try:
- modified_on = stat(filepath)[-2]
- except OSError:
- # this typically happens on emacs backup files (.#foo.py)
- self.warning('Unable to load %s. It is likely to be a backup file',
- filepath)
- return False
- if filepath in self._lastmodifs:
- # only load file if it was modified
- if modified_on <= self._lastmodifs[filepath]:
- return
- # if it was modified, raise RegistryOutOfDate to reload everything
- self.info('File %s changed since last visit', filepath)
- raise RegistryOutOfDate()
+ mdate = self._mdate(filepath)
+ if mdate is None:
+ return # backup file, see _mdate implementation
# set update time before module loading, else we get some reloading
# weirdness in case of syntax error or other error while importing the
# module
- self._lastmodifs[filepath] = modified_on
+ self._lastmodifs[filepath] = mdate
# load the module
module = load_module_from_name(modname, use_sys=not force_reload)
self.load_module(module)
- return True
def load_module(self, module):
self.info('loading %s', module)
--- a/web/uicfg.py Thu Apr 15 12:47:02 2010 +0200
+++ b/web/uicfg.py Thu Apr 15 12:48:40 2010 +0200
@@ -8,107 +8,6 @@
To configure the interface generation, we use ``RelationTag`` objects.
-Primary view configuration
-``````````````````````````
-
-XXX section moved to the doc, is maintained there
-
-If you want to customize the primary view of an entity, overriding the primary
-view class may not be necessary. For simple adjustments (attributes or relations
-display locations and styles), a much simpler way is to use uicfg.
-
-Attributes/relations display location
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-In the primary view, there are 3 sections where attributes and relations can be
-displayed (represented in pink in the image below):
-
-* attributes
-* relations
-* sideboxes
-
-.. image:: ../../images/primaryview_template.png
-
-
-**Attributes** can only be displayed in the attributes section (default
- behavior). They can also be hidden.
-
-For instance, to hide the ``title`` attribute of the ``Blog`` entity:
-
-.. sourcecode:: python
-
- from cubicweb.web import uicfg
- uicfg.primaryview_section.tag_attribute(('Blog', 'title'), 'hidden')
-
-
-**Relations** can be either displayed in one of the three sections or hidden.
-
-For relations, there are two methods:
-
-* ``tag_object_of`` for modifying the primary view of the object
-* ``tag_subject_of`` for modifying the primary view of the subject
-
-These two methods take two arguments:
-
-* a triplet ``(subject, relation_name, object)``, where subject or object can be replaced with ``'*'``
-* the section name or ``hidden``
-
-.. sourcecode:: python
-
- # hide every relation ``entry_of`` in the ``Blog`` primary view
- uicfg.primaryview_section.tag_object_of(('*', 'entry_of', 'Blog'), 'hidden')
-
- # display ``entry_of`` relations in the ``relations`` section in the ``BlogEntry`` primary view
- uicfg.primaryview_section.tag_subject_of(('BlogEntry', 'entry_of', '*'),
- 'relations')
-
-
-Display content
-^^^^^^^^^^^^^^^
-
-You can use ``primaryview_display_ctrl`` to customize the display of attributes
-or relations. Values of ``primaryview_display_ctrl`` are dictionaries.
-
-
-Common keys for attributes and relations are:
-* ``vid``: specifies the regid of the view for displaying the attribute or the relation.
-
- If ``vid`` is not specified, the default value depends on the section:
- * ``attributes`` section: 'reledit' view
- * ``relations`` section: 'autolimited' view
- * ``sideboxes`` section: 'sidebox' view
-
-* ``order``: int used to control order within a section. When not specified,
- automatically set according to order in which tags are added.
-
-
-Keys for relations only:
-
-* ``label``: label for the relations section or side box
-
-* ``showlabel``: boolean telling whether the label is displayed
-
-* ``limit``: boolean telling if the results should be limited. If so, a link to all results is displayed
-
-* ``filter``: callback taking the related result set as argument and returning it filtered
-
-.. sourcecode:: python
-
- # in ``CWUser`` primary view, display ``created_by`` relations in relations section
- uicfg.primaryview_section.tag_object_of(('*', 'created_by', 'CWUser'), 'relations')
-
- # displays this relation as a list, sets the label, limits the number of results and filters on comments
- uicfg.primaryview_display_ctrl.tag_object_of(
- ('*', 'created_by', 'CWUser'),
- {'vid': 'list', 'label': _('latest comment(s):'), 'limit': True,
- 'filter': lambda rset: rset.filtered_rset(lambda x: x.e_schema == 'Comment')})
-
-.. Warning:: with the ``primaryview_display_ctrl`` rtag, the subject or the
- object of the relation is ignored for respectively ``tag_object_of`` or
- ``tag_subject_of``. To avoid warnings during execution, they should be set to
- ``'*'``.
-
-
Index view configuration
````````````````````````
:indexview_etype_section: