[doc/book] regroup views chapters under common umbrella (in the development part) & some fixes
--- a/doc/book/en/development/devweb/controllers.rst Wed Apr 14 18:54:28 2010 +0200
+++ b/doc/book/en/development/devweb/controllers.rst Thu Apr 15 10:58:21 2010 +0200
@@ -152,15 +152,13 @@
* 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_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`).
+ * 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
--- a/doc/book/en/development/devweb/index.rst Wed Apr 14 18:54:28 2010 +0200
+++ b/doc/book/en/development/devweb/index.rst Thu Apr 15 10:58:21 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 Wed Apr 14 18:54:28 2010 +0200
+++ b/doc/book/en/development/devweb/rtags.rst Thu Apr 15 10:58:21 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 Wed Apr 14 18:54:28 2010 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,131 +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.
-
-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/autoform.rst Thu Apr 15 10:58:21 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 10:58:21 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/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.
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/book/en/development/devweb/views/baseviews.rst Thu Apr 15 10:58:21 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 10:58:21 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 10:58:21 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 10:58:21 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 10:58:21 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 10:58:21 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 10:58:21 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/primary.rst Thu Apr 15 10:58:21 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 10:58:21 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 10:58:21 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 10:58:21 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 10:58:21 2010 +0200
@@ -0,0 +1,131 @@
+
+.. _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.
+
+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 10:58:21 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 10:58:21 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/index.rst Wed Apr 14 18:54:28 2010 +0200
+++ b/doc/book/en/development/index.rst Thu Apr 15 10:58:21 2010 +0200
@@ -19,5 +19,4 @@
devrepo/index
testing.rst
migration.rst
- webstdlib/index
profiling.rst
--- a/doc/book/en/development/testing.rst Wed Apr 14 18:54:28 2010 +0200
+++ b/doc/book/en/development/testing.rst Thu Apr 15 10:58:21 2010 +0200
@@ -1,10 +1,8 @@
.. -*- coding: utf-8 -*-
+
Tests
=====
-.. toctree::
- :maxdepth: 1
-
Unit tests
----------
@@ -89,8 +87,9 @@
You can see an example of security tests in the
:ref:`adv_tuto_security`.
-It is possible to have these tests run continuously using `apycot`
-(http://www.logilab.org/project/apycot).
+It is possible to have these tests run continuously using `apycot`_.
+
+.. _apycot: http://www.logilab.org/project/apycot
Managing connections or users
+++++++++++++++++++++++++++++
@@ -220,9 +219,12 @@
Using Pytest
````````````
-`pytest` is an utility that extends the Python unittest functionality
-and is the preferred way to run the CubicWeb test suites. Bare
-unittests also work the usual way.
+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:
@@ -254,4 +256,3 @@
``````````````
.. autoclass:: cubicweb.devtools.testlib.CubicWebTC
:members:
-
--- a/doc/book/en/development/webstdlib/autoform.rst Wed Apr 14 18:54:28 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 Wed Apr 14 18:54:28 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 Wed Apr 14 18:54:28 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 Wed Apr 14 18:54:28 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 Wed Apr 14 18:54:28 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/editforms.rst Wed Apr 14 18:54:28 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 Wed Apr 14 18:54:28 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 Wed Apr 14 18:54:28 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 Wed Apr 14 18:54:28 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 Wed Apr 14 18:54:28 2010 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,26 +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
- urlpublish
- breadcrumbs
- facets
- wdoc
- embedding
- idownloadable
--- a/doc/book/en/development/webstdlib/primary.rst Wed Apr 14 18:54:28 2010 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,312 +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.
-
-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
--- a/doc/book/en/development/webstdlib/startup.rst Wed Apr 14 18:54:28 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 Wed Apr 14 18:54:28 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 Wed Apr 14 18:54:28 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 Wed Apr 14 18:54:28 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 Wed Apr 14 18:54:28 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
-
-
-